1.1.13: will be tagged as "sbcl-1.1.13"
[sbcl.git] / src / code / macroexpand.lisp
index ca38c6c..cb60c38 100644 (file)
                        t)
                (values form nil))))
         ((symbolp form)
-         (let* ((venv (when env (sb!c::lexenv-vars env)))
-                (local-def (cdr (assoc form venv))))
-           (cond ((and (consp local-def)
-                       (eq (car local-def) 'macro))
-                  (values (cdr local-def) t))
-                 (local-def
-                  (values form nil))
-                 ((eq (info :variable :kind form) :macro)
-                  (values (info :variable :macro-expansion form) t))
-                 (t
-                  (values form nil)))))
+         (flet ((perform-symbol-expansion (symbol expansion)
+                  ;; CLHS 3.1.2.1.1 specifies that symbol-macros are expanded
+                  ;; via the macroexpand hook, too.
+                  (funcall sb!xc:*macroexpand-hook*
+                           (constantly expansion)
+                           symbol
+                           env)))
+           (let* ((venv (when env (sb!c::lexenv-vars env)))
+                  (local-def (cdr (assoc form venv))))
+             (cond ((and (consp local-def)
+                         (eq (car local-def) 'macro))
+                    (values (perform-symbol-expansion form (cdr local-def)) t))
+                   (local-def
+                    (values form nil))
+                   ((eq (info :variable :kind form) :macro)
+                    (let ((expansion (info :variable :macro-expansion form)))
+                      (values (perform-symbol-expansion form expansion) t)))
+                   (t
+                    (values form nil))))))
         (t
          (values form nil))))
 
                    (frob new-form t)
                    (values new-form expanded)))))
     (frob form nil)))
+
+;;; Like MACROEXPAND-1, but takes care not to expand special forms.
+(defun %macroexpand-1 (form &optional env)
+  (if (or (atom form)
+          (let ((op (car form)))
+            (not (and (symbolp op) (sb!xc:special-operator-p op)))))
+      (sb!xc:macroexpand-1 form env)
+      (values form nil)))
+
+;;; Like MACROEXPAND, but takes care not to expand special forms.
+(defun %macroexpand (form &optional env)
+  (labels ((frob (form expanded)
+             (multiple-value-bind (new-form newly-expanded-p)
+                 (%macroexpand-1 form env)
+               (if newly-expanded-p
+                   (frob new-form t)
+                   (values new-form expanded)))))
+    (frob form nil)))