Replace DEF!METHOD and SB!XC:DEFMETHOD with just DEFMETHOD.
[sbcl.git] / src / code / defbangstruct.lisp
blobca1789c8686dc45ea6d454f989bf2e7d35ca2a35
1 ;;;; DEF!STRUCT = bootstrap DEFSTRUCT, a wrapper around DEFSTRUCT which
2 ;;;; provides special features to help at bootstrap time:
3 ;;;; 1. Layout information, inheritance information, and so forth is
4 ;;;; retained in such a way that we can get to it even on vanilla
5 ;;;; ANSI Common Lisp at cross-compiler build time.
6 ;;;; 2. MAKE-LOAD-FORM information is stored in such a way that we can
7 ;;;; get to it at bootstrap time before CLOS is built. This is
8 ;;;; important because at least as of sbcl-0.6.11.26, CLOS is built
9 ;;;; (compiled) after cold init, so we need to have the compiler
10 ;;;; even before CLOS runs.
12 ;;;; This software is part of the SBCL system. See the README file for
13 ;;;; more information.
14 ;;;;
15 ;;;; This software is derived from the CMU CL system, which was
16 ;;;; written at Carnegie Mellon University and released into the
17 ;;;; public domain. The software is in the public domain and is
18 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
19 ;;;; files for more information.
21 (in-package "SB!KERNEL")
23 ;;; Has the type system been properly initialized? (I.e. is it OK to
24 ;;; use it?)
25 (!defglobal *type-system-initialized* nil)
27 ;;; A bootstrap MAKE-LOAD-FORM method can be a function or the name
28 ;;; of a function.
29 (deftype def!struct-type-make-load-form-fun () '(or function symbol))
31 ;;; a little single-inheritance system to keep track of MAKE-LOAD-FORM
32 ;;; information for DEF!STRUCT-defined types
33 (eval-when (#-sb-xc :compile-toplevel :load-toplevel :execute)
35 ;; (DEF!STRUCT-SUPERTYPE TYPE) is the DEF!STRUCT-defined type that
36 ;; TYPE inherits from, or NIL if none.
37 (defvar *def!struct-supertype* (make-hash-table))
38 (defun def!struct-supertype (type)
39 (multiple-value-bind (value value-p) (gethash type *def!struct-supertype*)
40 (unless value-p
41 (error "~S is not a DEF!STRUCT-defined type." type))
42 value))
43 (defun (setf def!struct-supertype) (value type)
44 (when (and value #-sb-xc-host *type-system-initialized*)
45 (aver (subtypep value 'structure!object))
46 (aver (subtypep type value)))
47 (setf (gethash type *def!struct-supertype*) value))
49 ;; (DEF!STRUCT-TYPE-MAKE-LOAD-FORM-FUN TYPE) is the load form
50 ;; generator associated with the DEF!STRUCT-defined structure named
51 ;; TYPE, stored in a way which works independently of CLOS. The
52 ;; *DEF!STRUCT-TYPE-MAKE-LOAD-FORM-FUN* table is used to store the
53 ;; values. All types defined by DEF!STRUCT have an entry in the
54 ;; table; those with no MAKE-LOAD-FORM function have an explicit NIL
55 ;; entry.
56 (defvar *def!struct-type-make-load-form-fun* (make-hash-table))
57 (defun def!struct-type-make-load-form-fun (type)
58 (do ((supertype type))
59 (nil)
60 (multiple-value-bind (value value-p)
61 (gethash supertype *def!struct-type-make-load-form-fun*)
62 (unless value-p
63 (error "~S (supertype of ~S) is not a DEF!STRUCT-defined type."
64 supertype
65 type))
66 (when value
67 (return value))
68 (setf supertype (def!struct-supertype supertype))
69 (unless supertype
70 (error "There is no MAKE-LOAD-FORM function for bootstrap type ~S."
71 type)))))
72 (defun (setf def!struct-type-make-load-form-fun) (new-value type)
73 (when #+sb-xc-host t #-sb-xc-host *type-system-initialized*
74 (aver (subtypep type 'structure!object))
75 (aver (typep new-value 'def!struct-type-make-load-form-fun)))
76 (setf (gethash type *def!struct-type-make-load-form-fun*) new-value)))
78 ;;; the simplest, most vanilla MAKE-LOAD-FORM function for DEF!STRUCT
79 ;;; objects, which is just to dump as a sequence of descriptor words.
80 ;;; The target compiler can do this efficiently whenever it sees that a
81 ;;; MAKE-LOAD-FORM method returned the result of MAKE-LOAD-FORM-SAVING-SLOTS
82 ;;; with all slots saved - there is no magic keyword involved.
83 ;;; It would be nice to eliminate such voodoo here, but it won't be easy,
84 ;;; because the whole mechanism doesn't really work until PCL is bootstrapped.
85 (defun just-dump-it-normally (object &optional (env nil env-p))
86 (declare (type structure!object object))
87 (declare (ignorable env env-p object))
88 ;; KLUDGE: we require essentially three different behaviours of
89 ;; JUST-DUMP-IT-NORMALLY, two of which (host compiler's
90 ;; MAKE-LOAD-FORM, cross-compiler's MAKE-LOAD-FORM) are handled by
91 ;; the #+SB-XC-HOST clause. The #-SB-XC-HOST clause is the
92 ;; behaviour required by the target, before the CLOS-based
93 ;; MAKE-LOAD-FORM-SAVING-SLOTS is implemented.
94 #+sb-xc-host
95 (if env-p
96 (sb!xc:make-load-form-saving-slots object :environment env)
97 (sb!xc:make-load-form-saving-slots object))
98 #-sb-xc-host
99 :sb-just-dump-it-normally)
101 ;;; a MAKE-LOAD-FORM function for objects which don't use the load
102 ;;; form system. This is used for LAYOUT objects because the special
103 ;;; dumping requirements of LAYOUT objects are met by using special
104 ;;; VOPs which bypass the load form system. It's also used for various
105 ;;; compiler internal structures like nodes and VOP-INFO (FIXME:
106 ;;; Why?).
107 (defun ignore-it (object &optional env)
108 (declare (type structure!object object))
109 (declare (ignore object env))
110 ;; This magic tag is handled specially by the compiler downstream.
111 :ignore-it)
113 ;;; machinery used in the implementation of DEF!STRUCT
114 #+sb-xc-host
115 (eval-when (:compile-toplevel :load-toplevel :execute)
116 ;; a description of a DEF!STRUCT call to be stored until we get
117 ;; enough of the system running to finish processing it
118 (defstruct delayed-def!struct
119 (args (missing-arg) :type cons)
120 (package (sane-package) :type package))
121 ;; a list of DELAYED-DEF!STRUCTs stored until we get DEF!STRUCT
122 ;; working fully so that we can apply it to them then. After
123 ;; DEF!STRUCT is made to work fully, this list is processed, then
124 ;; made unbound, and should no longer be used.
125 (defvar *delayed-def!structs* nil))
126 (eval-when (#-sb-xc :compile-toplevel :load-toplevel :execute)
127 ;; Parse the arguments for a DEF!STRUCT call, and return
128 ;; (VALUES NAME DEFSTRUCT-ARGS MAKE-LOAD-FORM-FUN DEF!STRUCT-SUPERTYPE),
129 ;; where NAME is the name of the new type, DEFSTRUCT-ARGS is the
130 ;; munged result suitable for passing on to DEFSTRUCT,
131 ;; MAKE-LOAD-FORM-FUN is the make load form function, or NIL if
132 ;; there's none, and DEF!STRUCT-SUPERTYPE is the direct supertype of
133 ;; the type if it is another DEF!STRUCT-defined type, or NIL
134 ;; otherwise.
135 (defun parse-def!struct-args (nameoid &rest rest)
136 (multiple-value-bind (name options) ; Note: OPTIONS can change below.
137 (if (consp nameoid)
138 (values (first nameoid) (rest nameoid))
139 (values nameoid nil))
140 (declare (type list options))
141 (let* ((include-clause (find :include options :key #'first))
142 (def!struct-supertype nil) ; may change below
143 (mlff-clause (find :make-load-form-fun options :key #'first))
144 (mlff (and mlff-clause (second mlff-clause))))
145 (when (find :type options :key #'first)
146 (error "can't use :TYPE option in DEF!STRUCT"))
147 (when mlff-clause
148 (setf options (remove mlff-clause options)))
149 (when include-clause
150 (setf def!struct-supertype (second include-clause)))
151 (if (eq name 'structure!object) ; if root of hierarchy
152 (aver (not include-clause))
153 (unless include-clause
154 (setf def!struct-supertype 'structure!object)
155 (push `(:include ,def!struct-supertype) options)))
156 (values name `((,name ,@options) ,@rest) mlff def!struct-supertype)))))
158 ;;; a helper function for DEF!STRUCT in the #+SB-XC-HOST case: Return
159 ;;; DEFSTRUCT-style arguments with any class names in the SB!XC
160 ;;; package (i.e. the name of the class being defined, and/or the
161 ;;; names of classes in :INCLUDE clauses) converted from SB!XC::FOO to
162 ;;; CL::FOO.
163 #+sb-xc-host
164 (eval-when (:compile-toplevel :load-toplevel :execute)
165 (defun uncross-defstruct-args (defstruct-args)
166 (destructuring-bind (name-and-options &rest slots-and-doc) defstruct-args
167 (multiple-value-bind (name options)
168 (if (symbolp name-and-options)
169 (values name-and-options nil)
170 (values (first name-and-options)
171 (rest name-and-options)))
172 (flet ((uncross-option (option)
173 (if (eq (first option) :include)
174 (destructuring-bind
175 (include-keyword included-name &rest rest)
176 option
177 `(,include-keyword
178 ,(uncross included-name)
179 ,@rest))
180 option)))
181 `((,(uncross name)
182 ,@(mapcar #'uncross-option options))
183 ,@slots-and-doc))))))
185 ;;; DEF!STRUCT's arguments are like DEFSTRUCT's arguments, except that
186 ;;; DEF!STRUCT accepts an extra optional :MAKE-LOAD-FORM-FUN clause.
187 ;;; DEF!STRUCT also does some magic to ensure that anything it defines
188 ;;; includes STRUCTURE!OBJECT, so that when CLOS is/becomes available,
189 ;;; we can hook the DEF!STRUCT system into
190 ;;; (DEFMETHOD MAKE-LOAD-FORM ((X STRUCTURE!OBJECT) &OPTIONAL ENV) ..)
191 ;;; and everything will continue to work.
192 (defmacro def!struct (&rest args)
193 (multiple-value-bind (name defstruct-args mlff def!struct-supertype)
194 (apply #'parse-def!struct-args args)
195 `(progn
196 ;; There are two valid cases here: creating the
197 ;; STRUCTURE!OBJECT root of the inheritance hierarchy, or
198 ;; inheriting from STRUCTURE!OBJECT somehow.
200 ;; The invalid case that we want to exclude is when an :INCLUDE
201 ;; clause was used, and the included class didn't inherit frmo
202 ;; STRUCTURE!OBJECT. We want to catch that error ASAP because
203 ;; otherwise the bug might lurk until someone tried to do
204 ;; MAKE-LOAD-FORM on an instance of the class.
205 ,@(if (eq name 'structure!object)
206 (aver (null def!struct-supertype))
207 `((aver (subtypep ',def!struct-supertype 'structure!object))))
208 (defstruct ,@defstruct-args)
209 (setf (def!struct-type-make-load-form-fun ',name)
210 ,(if (symbolp mlff)
211 `',mlff
212 mlff)
213 (def!struct-supertype ',name)
214 ',def!struct-supertype)
215 #+sb-xc-host ,(let ((u (uncross-defstruct-args defstruct-args)))
216 (if (boundp '*delayed-def!structs*)
217 `(push (make-delayed-def!struct :args ',u)
218 *delayed-def!structs*)
219 `(sb!xc:defstruct ,@u)))
220 ',name)))
222 ;;; When building the cross-compiler, this function has to be called
223 ;;; some time after SB!XC:DEFSTRUCT is set up, in order to take care
224 ;;; of any processing which had to be delayed until then.
225 #+sb-xc-host
226 (defun force-delayed-def!structs ()
227 (if (boundp '*delayed-def!structs*)
228 (progn
229 (mapcar (lambda (x)
230 (let ((*package* (delayed-def!struct-package x)))
231 ;; KLUDGE(?): EVAL is almost always the wrong thing.
232 ;; However, since we have to map DEFSTRUCT over the
233 ;; list, and since ANSI declined to specify any
234 ;; functional primitives corresponding to the
235 ;; DEFSTRUCT macro, it seems to me that EVAL is
236 ;; required in there somewhere..
237 (eval `(sb!xc:defstruct ,@(delayed-def!struct-args x)))))
238 (reverse *delayed-def!structs*))
239 ;; We shouldn't need this list any more. Making it unbound
240 ;; serves as a signal to DEF!STRUCT that it needn't delay
241 ;; DEF!STRUCTs any more. It is also generally a good thing for
242 ;; other reasons: it frees garbage, and it discourages anyone
243 ;; else from pushing anything else onto the list later.
244 (makunbound '*delayed-def!structs*))
245 ;; This condition is probably harmless if it comes up when
246 ;; interactively experimenting with the system by loading a source
247 ;; file into it more than once. But it's worth warning about it
248 ;; because it definitely shouldn't come up in an ordinary build
249 ;; process.
250 (warn "*DELAYED-DEF!STRUCTS* is already unbound.")))
252 ;;; The STRUCTURE!OBJECT abstract class is the base of the type
253 ;;; hierarchy for objects which have/use DEF!STRUCT functionality.
254 ;;; (The extra hackery in DEF!STRUCT-defined things isn't needed for
255 ;;; STRUCTURE-OBJECTs defined by ordinary, post-warm-init programs, so
256 ;;; it's only put into STRUCTURE-OBJECTs which inherit from
257 ;;; STRUCTURE!OBJECT.)
258 (def!struct (structure!object (:constructor nil) (:copier nil) (:predicate nil)))
260 ;;;; hooking this all into the standard MAKE-LOAD-FORM system
262 ;;; MAKE-LOAD-FORM for DEF!STRUCT-defined types
263 (defun structure!object-make-load-form (object &optional env)
264 (declare (ignore env))
265 (funcall (def!struct-type-make-load-form-fun (type-of object))
266 object))
268 ;;; Do the right thing at cold load time.
270 ;;; (Eventually this MAKE-LOAD-FORM function be overwritten by CLOS's
271 ;;; generic MAKE-LOAD-FORM, at which time a STRUCTURE!OBJECT method
272 ;;; should be added to call STRUCTURE!OBJECT-MAKE-LOAD-FORM.)
273 (setf (symbol-function 'sb!xc:make-load-form)
274 #'structure!object-make-load-form)
276 ;;; Do the right thing in the vanilla ANSI CLOS of the
277 ;;; cross-compilation host. (Something similar will have to be done in
278 ;;; our CLOS, too, but later, some time long after the toplevel forms
279 ;;; of this file have run.)
280 #+sb-xc-host
281 (defmethod make-load-form ((obj structure!object) &optional (env nil env-p))
282 (if env-p
283 (structure!object-make-load-form obj env)
284 (structure!object-make-load-form obj)))