- The standard provides constantp, which may take an environment. But eval takes no environment, always using the global environment.
- The value of a constant variable isn't necessarily available at the time constantp returns true (such as in the compilation environment).
- If we are passing information via symbol macros (e.g. doing compiler-let-like tricks) then we'd like an easy way to get those values.
(defun quoted-form-p (form) "Return true if FORM is a QUOTE special form." (typep form '(cons (eql quote) (cons t null)))) (defun self-evaluating-p (form) "Return true if FORM evaluates to itself (in any environment)." (typep form '(and atom (or null (eql t) keyword (not symbol))))) (defun constant-form-p (form) "Return true if FORM is a (bound) constant variable." (and (symbolp form) (constantp form) (boundp form))) (defun macro-eval (form &optional env) (prog ((expansion form) expanded-p) macro-eval-1 (when (self-evaluating-p expansion) (return (values expansion t))) (when (quoted-form-p expansion) (return (values (cadr expansion) t))) (multiple-value-setq (expansion expanded-p) (macroexpand-1 expansion env)) (when expanded-p (go macro-eval-1)) (return (if (constant-form-p expansion) ;; (1) We have a constant variable, and ;; (2) the value is actually available. (values (symbol-value expansion) t) ;; No evaluation. (values form nil)))))
Note that constantp is "not permitted" to expand compiler macros, but macro-eval could be extended to do this.
- The symbol-macrolet trick
- Issue COMPILER-LET-CONFUSION:ELIMINATE
- constantp values always available at macro expansion time?