ccl
ccl copied to clipboard
defstruct :include option too eagerly evaluated during macroexpansion
According to the language spec a toplevel symbol-macrolet form should evaluate its body as toplevel forms and the defstruct form with a :include option can have an argument which is "the name of some previously defined structure".
The serapeum library manages to run in a corner case with this in it's defunion macro.
I have recreated a minimal fail case with this:
(define-symbol-macro %include nil)
(defun get-%include (env)
(macroexpand-1 '%include env))
(defmacro deriv-mac (deriv &environment env)
`(defstruct (,deriv (:include ,(get-%include env)))))
(defmacro def-mac-chain (base deriv)
`(symbol-macrolet ((%include ,base))
(defstruct (,base))
(deriv-mac ,deriv)))
(def-mac-chain b d)
;;No such structure: (:INCLUDE Z)
;; [Condition of type SIMPLE-ERROR]
Rewriting it with ccl:compiler-let results in the same error.
What works though is the following definition:
(defmacro def-mac-chain (base deriv)
`(progn
(defstruct (,base))
(symbol-macrolet ((%include ,base))
(deriv-mac ,deriv)))
I suppose one can rewrite macros that expand to several deriving defstruct forms, but I think it would be more in the spirit of the standard if defstruct forms did not try to access their :include arguments during macroexpansion time.