jcbeaudoin / MKCL

ManKai Common Lisp
Other
33 stars 8 forks source link

define-symbol-macro requires eval-when #24

Closed davidmullen closed 6 months ago

davidmullen commented 6 months ago

This works interpreted:

(define-symbol-macro .test-symbol-macro.
  "Test Symbol Macro Value")

(defun test-value ()
  .test-symbol-macro.)

But the compiler gives a warning:

;;; Variable .TEST-SYMBOL-MACRO. was undefined. Compiler assumes it is a global.

And the symbol macro isn't expanded:

> (test-value)

Debugger called in: #<thread "Initial" active (26535) 0x7fc2d05d6740 7fc2cdb8b000>.

#<a UNBOUND-VARIABLE 140474510190656>:
    The variable .TEST-SYMBOL-MACRO. is unbound.

It works with an eval-when:

(eval-when
    (:compile-toplevel
     :load-toplevel
     :execute)
  (define-symbol-macro .test-symbol-macro.
    "Test Symbol Macro Value"))

(defun test-value ()
  .test-symbol-macro.)

I don't know if this is a matter of ANSI compliance, but it seems better—i.e. less surprising—if the compiler treats symbol macros the same way as regular macros. The standard says that for defmacro, "the compiler must store the macro definition at compile time, so that occurrences of the macro later on in the file can be expanded correctly." For define-symbol-macro, the standard doesn't say that, but it would seem to be implied.

jcbeaudoin commented 6 months ago

define-symbol-macro already wraps the output of its expansion in an eval-when, just not the one you expect. It currently lacks the :compile-toplevel part. I would also be inclined to consider this a bug and a (explainable) specification oversight.

BTW, define-compiler-macro seems to suffer from the same condition as define-symbol-macro, not so surprising since they share much of the same development history. Would you say that it too should be :compile-toplevel?

davidmullen commented 6 months ago

Yes, I noticed that about define-compiler-macro. I suppose the difference is that compiler macros aren't required by the standard to be expanded at all. But it's natural to expect a compiler macro to have a compile-time effect, particularly if the compiler macro is defined in the same file as the function that the compiler macro is for. So it appears typical for Common Lisp implementations to have :compile-toplevel in define-compiler-macro.

jcbeaudoin commented 6 months ago

How about what I just put on master/head (commit e517c6d). If that looks good to you it should close the issue.