ccl icon indicating copy to clipboard operation
ccl copied to clipboard

defstruct :include option too eagerly evaluated during macroexpansion

Open astrangeguy opened this issue 4 years ago • 0 comments

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.

astrangeguy avatar Feb 20 '21 09:02 astrangeguy