0.7.8.44:
[sbcl.git] / src / code / defmacro.lisp
1 ;;;; DEFMACRO machinery
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 ;;; the guts of the DEFMACRO macro, pulled out into a separate
15 ;;; function in order to make it easier to express the common
16 ;;; bootstrap idiom
17 ;;;   CL:DEFMACRO SB!XC:DEFMACRO
18 ;;;   SB!XC:DEFMACRO CL:DEFMACRO
19 (eval-when (:compile-toplevel :load-toplevel :execute)
20   (defun %expander-for-defmacro (name lambda-list body)
21     (unless (symbolp name)
22       (error "The macro name ~S is not a symbol." name))
23     (when (special-operator-p name)
24       (error "The special operator ~S can't be redefined as a macro."
25              name))
26     (let ((whole (gensym "WHOLE-"))
27           (environment (gensym "ENV-")))
28       (multiple-value-bind (new-body local-decs doc)
29           (parse-defmacro lambda-list whole body name 'defmacro
30                           :environment environment)
31         (let ((def `(lambda (,whole ,environment)
32                       ,@local-decs
33                       (block ,name
34                         ,new-body))))
35           `(eval-when (:compile-toplevel :load-toplevel :execute)
36              (sb!c::%defmacro ',name #',def ',lambda-list ,doc)))))))
37
38 (macrolet
39     ((def (times set-args-p)
40        `(eval-when (,@times)
41           (defun sb!c::%defmacro (name definition lambda-list doc)
42             ;; old note (ca. 1985, maybe:-): "Eventually %%DEFMACRO
43             ;; should deal with clearing old compiler information for
44             ;; the functional value."
45             ,@(unless set-args-p
46                 '((declare (ignore lambda-list))))
47             (ecase (info :function :kind name)
48               ((nil))
49               (:function
50                ;; (remhash name *free-funs*)
51                (undefine-fun-name name)
52                (style-warn
53                 "~S is being redefined as a macro when it was ~
54                  previously ~(~A~) to be a function."
55                 name
56                 (info :function :where-from name)))
57               (:macro)
58               (:special-form
59                (error "The special form ~S can't be redefined as a macro."
60                       name)))
61             (clear-info :function :where-from name)
62             ;; FIXME: It would be nice to warn about DEFMACRO of an
63             ;; already-defined macro, but that's slightly hard to do
64             ;; because in common usage DEFMACRO is defined at compile
65             ;; time and then redefined at load time. We'd need to make a
66             ;; distinction between the defined-at-compile-time state and
67             ;; the defined-at-load-time state to make this work. (Trying
68             ;; to warn about duplicate DEFTYPEs runs into the same
69             ;; problem.)
70             #+nil (when (sb!xc:macro-function name)
71                     ;; Someday we could check for macro arguments
72                     ;; being incompatibly redefined. Doing this right
73                     ;; will involve finding the old macro lambda-list
74                     ;; and comparing it with the new one.
75                     (style-warn "redefining ~S in DEFMACRO" name))
76             (setf (sb!xc:macro-function name) definition
77                   (fdocumentation name 'function) doc)
78             ,(when set-args-p
79                    `(case (widetag-of definition)
80                       (#.sb!vm:closure-header-widetag
81                        (setf (%simple-fun-arglist (%closure-fun definition))
82                              lambda-list))
83                       ((#.sb!vm:simple-fun-header-widetag
84                         #.sb!vm:closure-fun-header-widetag)
85                        (setf (%simple-fun-arglist definition) lambda-list))))
86             name))))
87   (progn
88     (def (:load-toplevel :execute) #-sb-xc-host t #+sb-xc-host nil)
89     (def (:compile-toplevel) nil)))
90
91 ;;; Parse the definition and make an expander function. The actual
92 ;;; definition is done by %DEFMACRO which we expand into. After the
93 ;;; compiler has gotten the information it wants out of macro
94 ;;; definition, it compiles a call to %DEFMACRO which happens at load
95 ;;; time.
96 (defmacro sb!xc:defmacro (name lambda-list &rest body)
97   (%expander-for-defmacro name lambda-list body))
98
99 ;;; In the cross-compiler, we not only need to support the definition
100 ;;; of target macros at cross-compiler-build-time (with SB!XC:DEFMACRO
101 ;;; running in the cross-compilation host), we also need to support
102 ;;; the definition of target macros at target compilation time (with
103 ;;; CL:DEFMACRO processed by the cross-compiler)..
104 #+sb-xc-host
105 (sb!xc:defmacro defmacro (name lambda-list &rest body)
106   (%expander-for-defmacro name lambda-list body))
107
108 ;;; DEFMACRO-MUNDANELY is like SB!XC:DEFMACRO, except that it doesn't
109 ;;; have any EVAL-WHEN or IR1 magic associated with it, so it only
110 ;;; takes effect in :LOAD-TOPLEVEL or :EXECUTE situations.
111 (def!macro defmacro-mundanely (name lambda-list &body body)
112
113   ;; old way:
114   ;;(let ((whole (gensym "WHOLE-"))
115   ;;      (environment (gensym "ENVIRONMENT-")))
116   ;;  (multiple-value-bind (new-body local-decs doc)
117   ;;      (parse-defmacro lambda-list whole body name 'defmacro
118   ;;                      :environment environment)
119   ;;    `(progn
120   ;;       (setf (sb!xc:macro-function ',name)
121   ;;             (lambda (,whole ,environment)
122   ;;                 ,@local-decs
123   ;;                 (block ,name
124   ;;                 ,new-body)))
125   ;;       (setf (fdocumentation ',name 'macro)
126   ;;             ,doc)
127   ;;       ',name)))
128
129   `(let ()
130      (sb!xc:defmacro ,name ,lambda-list ,@body)))