Dump built-in-classoids as literals in genesis.
[sbcl.git] / src / compiler / globaldb.lisp
blob3b645e9377b3bc44b6b8b62f70bd0c5c56e28688
1 ;;;; This file provides a functional interface to global information
2 ;;;; about named things in the system. Information is considered to be
3 ;;;; global if it must persist between invocations of the compiler. The
4 ;;;; use of a functional interface eliminates the need for the compiler
5 ;;;; to worry about the actual representation. This is important, since
6 ;;;; the information may well have several representations.
7 ;;;;
8 ;;;; The database contains arbitrary Lisp values, addressed by a
9 ;;;; <Name,Info-Number> pair, where Info-Number is identified by
10 ;;;; a <Category,Kind> pair, each being a keyword. The Name is a thing
11 ;;;; which we are recording information about. [Names are compared by EQUAL.]
12 ;;;; Category and Kind create a taxonomy of the data values for a thing.
13 ;;;; For example, '+ names both a function and a variable, so has (at least)
14 ;;;; two categories of information. Within each category, we have several
15 ;;;; pieces of info, and in fact some of these have the same-named :Kind
16 ;;;; such as <:FUNCTION,:TYPE> and <:VARIABLE,:TYPE>.
17 ;;;; (And sometimes the Kind is literally :KIND, as a consequence of
18 ;;;; how users of the database desire to name their keys.)
20 ;;;; The relation between this file and 'info-vectors' is that the
21 ;;;; latter provides a fundamental mechanism to create property-list-like
22 ;;;; things whose "indicators" are restricted to small integers.
23 ;;;; The globaldb abstraction is layered on top of that and is responsible
24 ;;;; for translating <Category,Kind> to a small integer.
26 ;;;; This software is part of the SBCL system. See the README file for
27 ;;;; more information.
28 ;;;;
29 ;;;; This software is derived from the CMU CL system, which was
30 ;;;; written at Carnegie Mellon University and released into the
31 ;;;; public domain. The software is in the public domain and is
32 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
33 ;;;; files for more information.
35 (in-package "SB!C")
37 #-no-ansi-print-object
38 (defmethod print-object ((x meta-info) stream)
39 (print-unreadable-object (x stream)
40 (format stream "~S ~S, ~D" (meta-info-category x) (meta-info-kind x)
41 (meta-info-number x))))
43 ;;; Given any non-negative integer, return a prime number >= to it.
44 ;;;
45 ;;; FIXME: This logic should be shared with ALMOST-PRIMIFY in
46 ;;; hash-table.lisp. Perhaps the merged logic should be
47 ;;; PRIMIFY-HASH-TABLE-SIZE, implemented as a lookup table of primes
48 ;;; after integral powers of two:
49 ;;; #(17 37 67 131 ..)
50 ;;; (Or, if that's too coarse, after half-integral powers of two.) By
51 ;;; thus getting rid of any need for primality testing at runtime, we
52 ;;; could punt POSITIVE-PRIMEP, too.
53 (defun primify (x)
54 (declare (type unsigned-byte x))
55 (do ((n (logior x 1) (+ n 2)))
56 ((positive-primep n) n)))
58 ;;; Why do we suppress the :COMPILE-TOPLEVEL situation here when we're
59 ;;; running the cross-compiler? The cross-compiler (which was built
60 ;;; from these sources) has its version of these data and functions
61 ;;; defined in the same places we'd be defining into. We're happy with
62 ;;; its version, since it was compiled from the same sources, so
63 ;;; there's no point in overwriting its nice compiled version of this
64 ;;; stuff with our interpreted version. (And any time we're *not*
65 ;;; happy with its version, perhaps because we've been editing the
66 ;;; sources partway through bootstrapping, tch tch, overwriting its
67 ;;; version with our version would be unlikely to help, because that
68 ;;; would make the cross-compiler very confused.)
69 (defun !register-meta-info (metainfo)
70 (let* ((name (meta-info-kind metainfo))
71 (list (!get-meta-infos name)))
72 (set-info-value name +info-metainfo-type-num+
73 (cond ((not list) metainfo) ; unique, just store it
74 ((listp list) (cons metainfo list)) ; prepend to the list
75 (t (list metainfo list)))))) ; convert atom to a list
77 (defun !%define-info-type (category kind type-spec type-checker
78 validate-function default &optional id)
79 (awhen (meta-info category kind nil) ; if found
80 (when id
81 (aver (= (meta-info-number it) id)))
82 (return-from !%define-info-type it)) ; do nothing
83 (let ((id (or id (position nil *info-types* :start 1)
84 (error "no more INFO type numbers available"))))
85 (!register-meta-info
86 (setf (aref *info-types* id)
87 (!make-meta-info id category kind type-spec type-checker
88 validate-function default)))))
90 #-sb-xc
91 (setf (get '!%define-info-type :sb-cold-funcall-handler/for-effect)
92 (lambda (category kind type-spec checker validator default id)
93 ;; The SB!FASL: symbols are poor style, but the lesser evil.
94 ;; If exported, then they'll stick around in the target image.
95 ;; Perhaps SB-COLD should re-export some of these.
96 (declare (special sb!fasl::*dynamic* sb!fasl::*cold-layouts*))
97 (let ((layout (gethash 'meta-info sb!fasl::*cold-layouts*)))
98 (sb!fasl::cold-svset
99 (sb!fasl::cold-symbol-value '*info-types*)
101 (sb!fasl::write-slots
102 (sb!fasl::allocate-struct sb!fasl::*dynamic* layout)
103 'meta-info ; give the type name in lieu of layout
104 :category category :kind kind :type-spec type-spec
105 :type-checker checker :validate-function validator
106 :default default :number id)))))
108 ;;;; info types, and type numbers, part II: what's
109 ;;;; needed only at compile time, not at run time
111 ;;; Define a new type of global information.
112 ;;; CATEGORY/KIND form a two-part name for the piece of information,
113 ;;; DEFAULT is a defaulting expression, and TYPE-SPEC
114 ;;; is a type specifier which data values must satisfy.
115 ;;; Roughly speaking there is a hierarchy to the two-piece names
116 ;;; but this is a fiction that is not maintained anywhere in the internals.
118 ;;; If the defaulting expression's value is a function, it is called with
119 ;;; the name for which the information is being looked up; otherwise it is
120 ;;; taken as the default value. The defaulting expression is used each time
121 ;;; a value is needed when one hasn't been previously set. (The result
122 ;;; does not automatically become the new value for the piece of info.)
123 ;;; Should a default value be itself a function, this must be expressed as
124 ;;; :DEFAULT (CONSTANTLY #'<a-function-name>) to adhere to the convention
125 ;;; that default objects satisfying FUNCTIONP will always be funcalled.
127 (eval-when (:compile-toplevel :execute)
128 ;; This convoluted idiom creates a macro that disappears from the target,
129 ;; kind of an alternative to the "!" name convention.
130 (#+sb-xc-host defmacro
131 #-sb-xc-host sb!xc:defmacro
132 define-info-type ((category kind)
133 &key (type-spec (missing-arg))
134 (validate-function)
135 default)
136 (declare (type keyword category kind))
137 ;; There was formerly a remark that (COPY-TREE TYPE-SPEC) ensures repeatable
138 ;; fasls. That's not true now, probably never was. A compiler is permitted to
139 ;; coalesce EQUAL quoted lists and there's no defense against it, so why try?
140 `(!%define-info-type
141 ,category ,kind ',type-spec
142 ,(if (eq type-spec 't)
143 '#'identity
144 `(named-lambda "check-type" (x) (the ,type-spec x)))
145 ,validate-function ,default
146 ;; Rationale for hardcoding here is explained at INFO-VECTOR-FDEFN.
147 ,(or (and (eq category :function) (eq kind :definition)
148 +fdefn-info-num+)
149 #+sb-xc (meta-info-number (meta-info category kind))))))
152 (macrolet ((meta-info-or-lose (category kind)
153 ;; don't need to type-check META-INFO's result, since it
154 ;; defaults to signaling an error if no meta-info found.
155 `(truly-the meta-info (meta-info ,category ,kind))))
156 ;;; INFO is the standard way to access the database. It's settable.
158 ;;; Return the information of the specified CATEGORY and KIND for NAME.
159 ;;; The second value returned is true if there is any such information
160 ;;; recorded. If there is no information, the first value returned is
161 ;;; the default and the second value returned is NIL.
162 (defun info (category kind name)
163 (let ((info (meta-info category kind)))
164 (get-info-value name (meta-info-number info))))
166 (defun (setf info) (new-value category kind name)
167 (let ((info (meta-info category kind)))
168 (funcall (meta-info-type-checker info) new-value)
169 (awhen (meta-info-validate-function info)
170 (funcall it name new-value))
171 (set-info-value name (meta-info-number info) new-value)))
173 ;; Clear the information of the specified CATEGORY and KIND for NAME in
174 ;; the current environment. Return true if there was any info.
175 (defun clear-info (category kind name)
176 (let* ((info (meta-info category kind))
177 (info-number-list (list (meta-info-number info))))
178 (declare (dynamic-extent info-number-list))
179 (clear-info-values name info-number-list))))
181 (defun clear-info-values (name info-numbers)
182 (dolist (type info-numbers)
183 (aver (and (typep type 'info-number) (svref *info-types* type))))
184 ;; A call to UNCROSS was suspiciously absent, so I added this ERROR
185 ;; to be certain that it's not supposed to happen when building the xc.
186 #+sb-xc-xhost (error "Strange CLEAR-INFO building the xc: ~S ~S"
187 name info-numbers)
188 (let (new)
189 (with-globaldb-name (key1 key2) name
190 :simple
191 ;; If PACKED-INFO-REMOVE has nothing to do, it returns NIL,
192 ;; corresponding to the input that UPDATE-SYMBOL-INFO expects.
193 (dx-flet ((clear-simple (old)
194 (setq new (packed-info-remove old key2 info-numbers))))
195 (update-symbol-info key1 #'clear-simple))
196 :hairy
197 ;; The global hashtable is not imbued with knowledge of the convention
198 ;; for PACKED-INFO-REMOVE because that would render it less useful
199 ;; as a general-purpose global hashtable for other kinds of stuff
200 ;; that I might want it to store aside from packed infos.
201 ;; So here UPDATE might receive NIL but must not return NIL if
202 ;; there was a non-nil input. NIL doesn't mean "do nothing".
203 (dx-flet ((clear-hairy (old)
204 (if old
205 ;; if -REMOVE => nil, then update NEW but return OLD
206 (or (setq new (packed-info-remove
207 old +no-auxilliary-key+ info-numbers))
208 old))))
209 (info-puthash *info-environment* name #'clear-hairy)))
210 (not (null new))))
212 ;;;; *INFO-ENVIRONMENT*
214 (defun !globaldb-cold-init ()
215 ;; Genesis writes the *INFO-TYPES* array, but setting up the mapping
216 ;; from keyword-pair to object is deferred until cold-init.
217 (dovector (x (the simple-vector *info-types*))
218 (when x (!register-meta-info x)))
219 (setq *info-environment* (make-info-hashtable)))
221 ;;;; GET-INFO-VALUE
223 ;;; If non-nil, *GLOBALDB-OBSERVER*'s CAR is a bitmask over info numbers
224 ;;; for which you'd like to call the function in the CDR whenever info
225 ;;; of that number is queried.
226 (!defvar *globaldb-observer* nil)
227 (declaim (type (or (cons (unsigned-byte #.(ash 1 info-number-bits)) function)
228 null) *globaldb-observer*))
229 #-sb-xc-host (declaim (always-bound *globaldb-observer*))
231 ;;; Return the value of NAME / INFO-NUMBER from the global environment,
232 ;;; or return the default if there is no global info.
233 ;;; The secondary value indicates whether info was found vs defaulted.
234 (declaim (ftype (sfunction (t info-number) (values t boolean))
235 get-info-value))
236 (defun get-info-value (name info-number)
237 (let* ((hook *globaldb-observer*)
238 (hookp (and (and hook
239 (not (eql 0 (car hook)))
240 (logbitp info-number (car hook))))))
241 (multiple-value-bind (vector aux-key)
242 (let ((name (uncross name)))
243 (with-globaldb-name (key1 key2) name
244 ;; In the :simple branch, KEY1 is no doubt a symbol,
245 ;; but constraint propagation isn't informing the compiler here.
246 :simple (values (symbol-info-vector (truly-the symbol key1)) key2)
247 :hairy (values (info-gethash name *info-environment*)
248 +no-auxilliary-key+)))
249 (when vector
250 (let ((index (packed-info-value-index vector aux-key info-number)))
251 (when index
252 (let ((answer (svref vector index)))
253 (when hookp
254 (funcall (truly-the function (cdr hook))
255 name info-number answer t))
256 (return-from get-info-value (values answer t)))))))
257 (let* ((def (meta-info-default (aref *info-types* info-number)))
258 (answer (if (functionp def) (funcall def name) def)))
259 (when hookp
260 (funcall (truly-the function (cdr hook)) name info-number answer nil))
261 (values answer nil))))
263 ;; Call FUNCTION once for each Name in globaldb that has information associated
264 ;; with it, passing the function the Name as its only argument.
266 (defun call-with-each-globaldb-name (fun-designator)
267 (let ((function (coerce fun-designator 'function)))
268 (with-package-iterator (iter (list-all-packages) :internal :external)
269 (loop (multiple-value-bind (winp symbol access package) (iter)
270 (declare (ignore access))
271 (if (not winp) (return))
272 ;; Try to process each symbol at most once by associating it with
273 ;; a single package. If a symbol is apparently uninterned,
274 ;; always keep it since we can't know if it has been seen once.
275 (when (or (not (symbol-package symbol))
276 (eq package (symbol-package symbol)))
277 (dolist (name (info-vector-name-list symbol))
278 (funcall function name))))))
279 (info-maphash (lambda (name data)
280 (declare (ignore data))
281 (funcall function name))
282 *info-environment*)))
284 ;;;; ":FUNCTION" subsection - Data pertaining to globally known functions.
286 (define-info-type (:function :definition) :type-spec (or fdefn null))
288 ;;; the kind of functional object being described. If null, NAME isn't
289 ;;; a known functional object.
290 (define-info-type (:function :kind)
291 :type-spec (member nil :function :macro :special-form)
292 ;; I'm a little confused what the correct behavior of this default
293 ;; is. It's not clear how to generalize the FBOUNDP expression to
294 ;; the cross-compiler. As far as I can tell, NIL is a safe default
295 ;; -- it might keep the compiler from making some valid
296 ;; optimization, but it shouldn't produce incorrect code. -- WHN
297 ;; 19990330
298 :default
299 #+sb-xc-host nil
300 #-sb-xc-host (lambda (name) (if (fboundp name) :function nil)))
302 ;;; Indicates whether the function is deprecated.
303 (define-info-type (:function :deprecated)
304 :type-spec (or null deprecation-info))
306 (declaim (ftype (sfunction (t) ctype)
307 specifier-type ctype-of sb!kernel::ctype-of-array))
309 ;;; the ASSUMED-TYPE for this function, if we have to infer the type
310 ;;; due to not having a declaration or definition
311 (define-info-type (:function :assumed-type)
312 ;; FIXME: The type-spec really should be
313 ;; (or approximate-fun-type null)).
314 ;; It was changed to T as a hopefully-temporary hack while getting
315 ;; cold init problems untangled.
316 :type-spec t)
318 ;;; where this information came from:
319 ;;; :ASSUMED = from uses of the object
320 ;;; :DEFINED = from examination of the definition
321 ;;; :DEFINED-METHOD = implicit, incremental declaration by CLOS.
322 ;;; :DECLARED = from a declaration
323 ;;; :DEFINED trumps :ASSUMED, :DEFINED-METHOD trumps :DEFINED,
324 ;;; and :DECLARED trumps :DEFINED-METHOD.
325 ;;; :DEFINED and :ASSUMED are useful for issuing compile-time warnings,
326 ;;; :DEFINED-METHOD and :DECLARED are useful for ANSIly specializing
327 ;;; code which implements the function, or which uses the function's
328 ;;; return values.
329 (define-info-type (:function :where-from)
330 :type-spec (member :declared :defined-method :assumed :defined)
331 :default
332 ;; Again [as in (DEFINE-INFO-TYPE (:FUNCTION :KIND) ...)] it's
333 ;; not clear how to generalize the FBOUNDP expression to the
334 ;; cross-compiler. -- WHN 19990606
335 #+sb-xc-host :assumed
336 #-sb-xc-host (lambda (name) (if (fboundp name) :defined :assumed)))
338 ;;; something which can be decoded into the inline expansion of the
339 ;;; function, or NIL if there is none
341 ;;; To inline a function, we want a lambda expression, e.g.
342 ;;; '(LAMBDA (X) (+ X 1)).
343 (define-info-type (:function :inline-expansion-designator)
344 :type-spec list)
346 ;;; This specifies whether this function may be expanded inline. If
347 ;;; null, we don't care.
348 (define-info-type (:function :inlinep) :type-spec inlinep)
350 ;;; Track how many times IR2 converted a call to this function as a full call
351 ;;; that was not in the scope of a local or global notinline declaration.
352 ;;; Useful for finding functions that were supposed to have been converted
353 ;;; through some kind of transformation but were not.
354 (define-info-type (:function :emitted-full-calls) :type-spec list)
356 ;;; a macro-like function which transforms a call to this function
357 ;;; into some other Lisp form. This expansion is inhibited if inline
358 ;;; expansion is inhibited.
359 ;;; As an exception, a cons of two atoms represents structure metadata
360 ;;; which is recognized and transformed in a stylized way.
362 ;;; This item is almost mutually exclusive with an inline expansion,
363 ;;; but both are possible in the rare case of a system-defined transform
364 ;;; that may decline to expand. If it does, an inline expansion could win.
365 ;;; We don't actually have anything like that any more though.
366 ;;; For user-defined functions, the invariant is maintained that at most
367 ;;; one of :source-transform and an inline-expansion exist.
368 (define-info-type (:function :source-transform)
369 :type-spec (or function null (cons atom atom)))
371 ;;; the macroexpansion function for this macro
372 (define-info-type (:function :macro-function) :type-spec (or function null))
374 ;;; the compiler-macroexpansion function for this function or macro
375 (define-info-type (:function :compiler-macro-function)
376 :type-spec (or function null))
378 ;;; a function which converts this special form into IR1
379 (define-info-type (:function :ir1-convert) :type-spec (or function null))
381 ;;; If a function is "known" to the compiler, then this is a FUN-INFO
382 ;;; structure containing the info used to special-case compilation.
383 (define-info-type (:function :info) :type-spec (or fun-info null))
385 ;;; This is a type specifier <t> such that if an argument X to the function
386 ;;; does not satisfy (TYPEP x <t>) then the function definitely returns NIL.
387 ;;; When the named function is a predicate that appears in (SATISFIES p)
388 ;;; specifiers, it is possible for type operations to see into the predicate
389 ;;; just enough to determine that something like
390 ;;; (AND (SATISFIES UNINTERESTING-METHOD-REDEFINITION-P) RATIONAL)
391 ;;; is *empty-type*, which in turn avoids type cache pollution.
392 (define-info-type (:function :predicate-truth-constraint) :type-spec t)
394 ;;;; ":VARIABLE" subsection - Data pertaining to globally known variables.
396 ;;; the kind of variable-like thing described
397 (define-info-type (:variable :kind)
398 :type-spec (member :special :constant :macro :global :alien :unknown)
399 :default (lambda (name)
400 (if (typep name '(or boolean keyword))
401 :constant
402 :unknown)))
404 (define-info-type (:variable :always-bound)
405 :type-spec (member nil :eventually :always-bound))
407 (define-info-type (:variable :deprecated)
408 :type-spec (or null deprecation-info))
410 ;;; the declared type for this variable
411 (define-info-type (:variable :type)
412 :type-spec ctype
413 :default #+sb-xc-host (lambda (x)
414 (declare (special *universal-type*) (ignore x))
415 *universal-type*)
416 #-sb-xc-host *universal-type*)
418 ;;; where this type and kind information came from
419 (define-info-type (:variable :where-from)
420 :type-spec (member :declared :assumed :defined) :default :assumed)
422 ;;; the macro-expansion for symbol-macros
423 (define-info-type (:variable :macro-expansion) :type-spec t)
425 (define-info-type (:variable :alien-info)
426 :type-spec (or heap-alien-info null))
428 (define-info-type (:variable :documentation) :type-spec (or string null))
430 ;; :WIRED-TLS describes how SYMBOL-VALUE (implicit or not) should be compiled.
431 ;; - :ALWAYS-HAS-TLS means that calls to SYMBOL-VALUE should access the TLS
432 ;; with a fixed offset. The index is assigned no later than load-time of
433 ;; the file containing code thus compiled. Presence of an index in the
434 ;; image that performed compilation is irrelevant (for now).
435 ;; - :ALWAYS-THREAD-LOCAL implies a fixed offset, *and* that the check for
436 ;; no-tls-value may be elided. There is currently no way to set this.
437 ;; Note that this does not affect elision of the check for unbound-marker
438 ;; which is under control of the :ALWAYS-BOUND info.
439 ;; - an integer is a permanent index, and also implies :ALWAYS-THREAD-LOCAL.
440 ;; Specials in the CL package (notably reader/printer controls) use a wired-tls,
441 ;; whether or not we bind per-thread [if we don't, that's a bug!]
442 ;; We don't assume wired TLS more generally, because user code often defines
443 ;; thousands of DEFVARs, possibly due to poor style, or due to ANSI's stance
444 ;; that DEFCONSTANT is only for EQL-comparable objects. In such cases with
445 ;; more symbols than can be bound per-thread, the compiler won't exacerbate
446 ;; things by making the loader eagerly assign a TLS index to every symbol
447 ;; ever referenced by SYMBOL-VALUE or SET. Depletion should occur lazily.
449 (define-info-type (:variable :wired-tls)
450 :type-spec (or (member nil :always-has-tls :always-thread-local)
451 fixnum) ; the actual index, for thread slots (to be done)
452 :default
453 (lambda (symbol)
454 (declare (symbol symbol))
455 (and (eq (info :variable :kind symbol) :special)
456 #-sb-xc-host
457 (eq (symbol-package symbol) *cl-package*)
458 #+sb-xc-host
459 (flet ((external-in-package-p (pkg)
460 (and (string= (package-name (symbol-package symbol)) pkg)
461 (eq (nth-value 1 (find-symbol (string symbol) pkg))
462 :external))))
463 ;; I'm not worried about random extra externals in some bizarro
464 ;; host lisp. TLS assignment has no bearing on semantics at all.
465 (or (external-in-package-p "COMMON-LISP")
466 (external-in-package-p "SB-XC")))
467 :always-has-tls)))
469 ;;;; ":TYPE" subsection - Data pertaining to globally known types.
471 ;;; the kind of type described. We return :INSTANCE for standard types
472 ;;; that are implemented as structures. For PCL classes, that have
473 ;;; only been compiled, but not loaded yet, we return
474 ;;; :FORTHCOMING-DEFCLASS-TYPE.
475 ;;; The only major distinction between :PRIMITIVE and :DEFINED
476 ;;; is how badly the system complains about attempted redefinition.
477 (define-info-type (:type :kind)
478 :type-spec (member :primitive :defined :instance
479 :forthcoming-defclass-type nil)
480 :validate-function (lambda (name new-value)
481 (declare (ignore new-value))
482 ;; The compiler-macro signals an error
483 ;; on forward-referenced info-types.
484 #+sb-xc-host (declare (notinline info))
485 (when (info :declaration :recognized name)
486 (error 'declaration-type-conflict-error
487 :format-arguments (list name)))))
489 (define-info-type (:type :documentation) :type-spec (or string null))
491 ;;; The expander function for a defined type,
492 ;;; or a cons whose CAR is a function which is a builtin type translator.
493 (define-info-type (:type :expander) :type-spec (or function list))
495 ;;; If non-nil, then the type coresponding to this name. Note that if
496 ;;; this is a built-in class with a translation, then this is the
497 ;;; translation, not the class object. This info type keeps track of
498 ;;; various atomic types (NIL etc.) and also serves as a means to
499 ;;; ensure that common standard types are only consed once.
500 (define-info-type (:type :builtin) :type-spec (or ctype null))
502 ;;; The classoid-cell for this type
503 (define-info-type (:type :classoid-cell) :type-spec t)
505 ;;; DEFTYPE lambda-list
506 ;; FIXME: remove this after making swank-fancy-inspector not use it.
507 (define-info-type (:type :lambda-list) :type-spec t)
509 (define-info-type (:type :source-location) :type-spec t)
511 ;;; Indicates whether the type is deprecated.
512 (define-info-type (:type :deprecated)
513 :type-spec (or null deprecation-info))
515 ;;;; ":TYPED-STRUCTURE" subsection.
516 ;;;; Data pertaining to structures that used DEFSTRUCT's :TYPE option.
517 (define-info-type (:typed-structure :info) :type-spec t)
518 (define-info-type (:typed-structure :documentation) :type-spec (or string null))
520 ;;;; ":DECLARATION" subsection - Data pertaining to user-defined declarations.
521 ;; CLTL2 offers an API to provide a list of known declarations, but it is
522 ;; inefficient to iterate over all symbols to find ones which have the
523 ;; (:DECLARATION :RECOGNIZED) info.
524 ;; Therefore maintain a list of recognized declarations. This list makes the
525 ;; globaldb storage of same redundant, but oh well.
526 (defglobal *recognized-declarations* nil)
527 (define-info-type (:declaration :recognized)
528 :type-spec boolean
529 ;; There's no portable way to unproclaim that a symbol is a declaration,
530 ;; but at the low-level permit new-value to be NIL.
531 :validate-function (lambda (name new-value)
532 (declare (symbol name))
533 (cond (new-value
534 (when (info :type :kind name)
535 (error 'declaration-type-conflict-error
536 :format-arguments (list name)))
537 (pushnew name *recognized-declarations*))
539 (setq *recognized-declarations*
540 (delete name *recognized-declarations*))))))
542 (define-info-type (:declaration :handler) :type-spec (or function null))
544 ;;;; ":ALIEN-TYPE" subsection - Data pertaining to globally known alien-types.
545 (define-info-type (:alien-type :kind)
546 :type-spec (member :primitive :defined :unknown)
547 :default :unknown)
548 (define-info-type (:alien-type :translator) :type-spec (or function null))
549 (define-info-type (:alien-type :definition) :type-spec (or alien-type null))
550 (define-info-type (:alien-type :struct) :type-spec (or alien-type null))
551 (define-info-type (:alien-type :union) :type-spec (or alien-type null))
552 (define-info-type (:alien-type :enum) :type-spec (or alien-type null))
554 ;;;; ":SETF" subsection - Data pertaining to expansion of the omnipotent macro.
555 (define-info-type (:setf :inverse) :type-spec (or symbol null))
556 (define-info-type (:setf :documentation) :type-spec (or string null))
557 (define-info-type (:setf :expander)
558 :type-spec (or function (cons integer function) null))
560 ;;;; ":CAS" subsection - Like SETF but there are no "inverses", just expanders
561 (define-info-type (:cas :expander) :type-spec (or function null))
563 ;;;; ":RANDOM-DOCUMENTATION" subsection.
564 ;;; This is used for storing miscellaneous documentation types. The
565 ;;; stuff is an alist translating documentation kinds to values.
566 (define-info-type (:random-documentation :stuff) :type-spec list)
568 ;;;; ":SOURCE-LOCATION" subsection.
569 ;;; This is kind of the opposite of what I'd have thought more logical,
570 ;;; where each of the above categories has one of its kinds of information
571 ;;; being :SOURCE-LOCATION.
572 ;;; And in fact that *is* how :TYPE was handled. However, many global entities
573 ;;; store their source-location hanging off some other hook, avoiding the
574 ;;; globaldb entirely, such as functions using a #<code-component>.
575 ;;; So either way is basically a hodgepodge.
577 (define-info-type (:source-location :variable) :type-spec t)
578 (define-info-type (:source-location :constant) :type-spec t)
579 (define-info-type (:source-location :typed-structure) :type-spec t)
580 (define-info-type (:source-location :symbol-macro) :type-spec t)
581 (define-info-type (:source-location :vop) :type-spec t)
582 (define-info-type (:source-location :declaration) :type-spec t)
583 (define-info-type (:source-location :alien-type) :type-spec t)
585 ;; This is for the SB-INTROSPECT contrib module, and debugging.
586 (defun call-with-each-info (function symbol)
587 (awhen (symbol-info-vector symbol)
588 (%call-with-each-info function it symbol)))
590 ;; This is for debugging at the REPL.
591 (defun show-info (sym)
592 (let ((prev 0))
593 (call-with-each-info
594 (lambda (name type-num val)
595 (unless (eq name prev)
596 (format t "~&~S" (setq prev name)))
597 (let ((type (svref *info-types* type-num)))
598 (format t "~& ~@[type ~D~]~@[~{~S ~S~}~] = "
599 (if (not type) type-num)
600 (if type
601 (list (meta-info-category type) (meta-info-kind type))))
602 (write val :level 1)))
603 sym)))