Yesterday, I wrote:
+---------------
| The [symbol macro] bug in CMUCL is understood, and a fix is in progress.
| There is no reason to avoid symbol macros unless you both must use CMUCL
| *and* cannot wait for a fix. [If you want to fix it yourself, the
| problem is in "src/code/eval.lisp", in the function MACROEXPAND-1.
| If you compare the first COND there with the similar one in the
| MACRO-FUNCTION function just above, the fix may be obvious.]
+---------------
Just so everyone knows, the modified version of MACROEXPAND-1
[attached below -- the change is in the first branch of the COND]
has been submitted to one of the CMUCL developers, who assures me
that it will be in the CVS tree "real soon now". Meanwhile, you
can compile/load this version into your copy of CMUCL-19c (wrap a
WITHOUT-PACKAGE-LOCKS around the LOAD) and the bug will go away.
Here's a test case:
> (defvar *foo* 13)
*FOO*
> (define-symbol-macro foo *foo*)
FOO
> (defun foo () foo)
FOO
> (let ((foo 57))
(list foo (incf foo) foo (foo)))
(57 58 58 13)
>
Without the patch, you'll get (57 14 57 14).
-Rob
-----
Rob Warnock <rpw3@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607
======= attachment: extracted from $CMUCL/src/code/eval.lisp ==============
(in-package "LISP")
;;; Macroexpand-1 -- Public
;;;
;;; The Env is a LEXENV or NIL (the null environment.)
;;;
(defun macroexpand-1 (form &optional env)
"If form is a macro (or symbol macro), expands it once. Returns two values,
the expanded form and a T-or-NIL flag indicating whether the form was, in
fact, a macro. Env is the lexical environment to expand in, which defaults
to the null environment."
(cond ((and (consp form) (symbolp (car form)))
(let ((def (macro-function (car form) env)))
(if def
(values (invoke-macroexpand-hook def form env) t)
(values form nil))))
((symbolp form)
(let* ((venv (when env (c::lexenv-variables env)))
(local-def (cdr (assoc form venv))))
(cond (local-def
(if (and (consp local-def)
(eq (car local-def) 'macro))
(values (cdr local-def) t)
(values form nil)))
((eq (info variable kind form) :macro)
(values (info variable macro-expansion form) t))
(t
(values form nil)))))
(t
(values form nil))))