Initial revision
[sbcl.git] / src / code / macroexpand.lisp
1 ;;;; MACROEXPAND and friends
2
3 ;;;; This software is part of the SBCL system. See the README file for
4 ;;;; more information.
5 ;;;;
6 ;;;; This software is derived from the CMU CL system, which was
7 ;;;; written at Carnegie Mellon University and released into the
8 ;;;; public domain. The software is in the public domain and is
9 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
10 ;;;; files for more information.
11
12 (in-package "SB!IMPL")
13
14 (file-comment
15   "$Header$")
16 \f
17 ;;;; syntactic environment access
18
19 (defun sb!xc:special-operator-p (symbol)
20   #!+sb-doc
21   "If the symbol globally names a special form, returns T, otherwise NIL."
22   (declare (symbol symbol))
23   (eq (info :function :kind symbol) :special-form))
24
25 (defvar sb!xc:*macroexpand-hook* 'funcall
26   #!+sb-doc
27   "The value of this variable must be a designator for a function that can
28   take three arguments, a macro expander function, the macro form to be
29   expanded, and the lexical environment to expand in. The function should
30   return the expanded form. This function is called by MACROEXPAND-1
31   whenever a runtime expansion is needed. Initially this is set to
32   FUNCALL.")
33
34 (declaim (ftype (function (t &optional (or null sb!c::lexenv))) sb!xc:macroexpand-1))
35 (defun sb!xc:macroexpand-1 (form &optional env)
36   #!+sb-doc
37   "If form is a macro (or symbol macro), expands it once. Returns two values,
38    the expanded form and a T-or-NIL flag indicating whether the form was, in
39    fact, a macro. Env is the lexical environment to expand in, which defaults
40    to the null environment."
41   (cond ((and (consp form) (symbolp (car form)))
42          (let ((def (sb!xc:macro-function (car form) env)))
43            (if def
44                (values (funcall sb!xc:*macroexpand-hook*
45                                 def
46                                 form
47                                 ;; As far as I can tell, it's not clear from
48                                 ;; the ANSI spec whether a MACRO-FUNCTION
49                                 ;; function needs to be prepared to handle
50                                 ;; NIL as a lexical environment. CMU CL
51                                 ;; passed NIL through to the MACRO-FUNCTION
52                                 ;; function, but I prefer SBCL "be conservative
53                                 ;; in what it sends and liberal in what it
54                                 ;; accepts" by doing the defaulting itself.
55                                 ;; -- WHN 19991128
56                                 (or env (make-null-lexenv)))
57                        t)
58                (values form nil))))
59         ((symbolp form)
60          (let* ((venv (when env (sb!c::lexenv-variables env)))
61                 (local-def (cdr (assoc form venv))))
62            (if (and (consp local-def)
63                     (eq (car local-def) 'macro))
64                (values (cdr local-def) t)
65                (values form nil))))
66         (t
67          (values form nil))))
68
69 (declaim (ftype (function (t &optional (or null sb!c::lexenv))) sb!xc:macroexpand))
70 (defun sb!xc:macroexpand (form &optional env)
71   #!+sb-doc
72   "Repetitively call MACROEXPAND-1 until the form can no longer be expanded.
73    Returns the final resultant form, and T if it was expanded. ENV is the
74    lexical environment to expand in, or NIL (the default) for the null
75    environment."
76   (labels ((frob (form expanded)
77              (multiple-value-bind (new-form newly-expanded-p)
78                  (sb!xc:macroexpand-1 form env)
79                (if newly-expanded-p
80                    (frob new-form t)
81                    (values new-form expanded)))))
82     (frob form nil)))