1 ;;;; type-related stuff which exists only in the target SBCL runtime
3 ;;;; This software is part of the SBCL system. See the README file for
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.
12 (in-package "SB!KERNEL")
14 (!begin-collecting-cold-init-forms)
18 ;;; Note that when cross-compiling, SB!XC:TYPEP is interpreted as
19 ;;; a test that the host Lisp object OBJECT translates to a target SBCL
20 ;;; type TYPE. (This behavior is needed e.g. to test for the validity of
21 ;;; numeric subtype bounds read when cross-compiling.)
22 (defun typep (object type)
24 "Return T iff OBJECT is of type TYPE."
27 ;;; If TYPE is a type that we can do a compile-time test on, then
28 ;;; return whether the object is of that type as the first value and
29 ;;; second value true. Otherwise return NIL, NIL.
31 ;;; We give up on unknown types and pick off FUNCTION and UNION types.
32 ;;; For structure types, we require that the type be defined in both
33 ;;; the current and compiler environments, and that the INCLUDES be
35 (defun ctypep (obj type)
36 (declare (type ctype type))
44 (values (%typep obj type) t))
46 (if (if (csubtypep type (specifier-type 'funcallable-instance))
47 (funcallable-instance-p obj)
48 (typep obj 'instance))
49 (if (eq (class-layout type)
50 (info :type :compiler-layout (sb!xc:class-name type)))
51 (values (sb!xc:typep obj type) t)
55 (dolist (mem (union-type-types type) (values nil t))
56 (multiple-value-bind (val win) (ctypep obj mem)
57 (unless win (return (values nil nil)))
58 (when val (return (values t t))))))
60 (values (functionp obj) t))
64 (values (alien-typep obj (alien-type-type-alien-type type)) t))
66 ;; Now the tricky stuff.
67 (let* ((hairy-spec (hairy-type-specifier type))
68 (symbol (if (consp hairy-spec) (car hairy-spec) hairy-spec)))
73 (dolist (spec (cdr hairy-spec) (values t t))
74 (multiple-value-bind (res win)
75 (ctypep obj (specifier-type spec))
76 (unless win (return (values nil nil)))
77 (unless res (return (values nil t)))))))
79 (multiple-value-bind (res win)
80 (ctypep obj (specifier-type (cadr hairy-spec)))
85 ;; KLUDGE: This stuff might well blow up if we tried to execute it
86 ;; when cross-compiling. But since for the foreseeable future the
87 ;; only code we'll try to cross-compile is SBCL itself, and SBCL is
88 ;; built without using SATISFIES types, it's arguably not important
89 ;; to worry about this. -- WHN 19990210.
90 (let ((fun (second hairy-spec)))
91 (cond ((and (consp fun)
92 (eq (car fun) 'lambda))
93 (values (not (null (funcall (coerce fun 'function) obj)))
95 ((and (symbolp fun) (fboundp fun))
96 (values (not (null (funcall fun obj))) t))
98 (values nil nil))))))))))
100 ;;; LAYOUT-OF -- Exported
102 ;;; Return the layout for an object. This is the basic operation for
103 ;;; finding out the "type" of an object, and is used for generic function
104 ;;; dispatch. The standard doesn't seem to say as much as it should about what
105 ;;; this returns for built-in objects. For example, it seems that we must
106 ;;; return NULL rather than LIST when X is NIL so that GF's can specialize on
108 #!-sb-fluid (declaim (inline layout-of))
110 (declare (optimize (speed 3) (safety 0)))
111 (cond ((typep x 'instance) (%instance-layout x))
112 ((funcallable-instance-p x) (%funcallable-instance-layout x))
114 ;; Note: was #.((CLASS-LAYOUT (SB!XC:FIND-CLASS 'NULL))).
115 ;; I (WHN 19990209) replaced this with an expression evaluated at
116 ;; run time in order to make it easier to build the cross-compiler.
117 ;; If it doesn't work, something else will be needed..
119 ;; KLUDGE: In order to really make it run at run time (instead of
120 ;; doing some weird broken thing at cold load time),
121 ;; we need to suppress a DEFTRANSFORM.. -- WHN 19991004
122 (declare (notinline sb!xc:find-class))
123 (class-layout (sb!xc:find-class 'null))))
124 (t (svref *built-in-class-codes* (get-type x)))))
126 #!-sb-fluid (declaim (inline sb!xc:class-of))
127 (defun sb!xc:class-of (object)
129 "Return the class of the supplied object, which may be any Lisp object, not
130 just a CLOS STANDARD-OBJECT."
131 (layout-class (layout-of object)))
133 ;;; Pull the type specifier out of a function object.
134 (defun extract-function-type (fun)
135 (if (sb!eval:interpreted-function-p fun)
136 (sb!eval:interpreted-function-type fun)
138 (byte-function (byte-function-type fun))
139 (byte-closure (byte-function-type (byte-closure-function fun)))
141 (specifier-type (%function-type (%closure-function fun)))))))
143 ;;;; miscellaneous interfaces
145 ;;; Clear memoization of all type system operations that can be
146 ;;; altered by type definition/redefinition.
147 (defun clear-type-caches ()
148 (when *type-system-initialized*
149 (dolist (sym '(values-specifier-type-cache-clear
150 values-type-union-cache-clear
151 type-union-cache-clear
152 values-subtypep-cache-clear
153 csubtypep-cache-clear
154 type-intersection-cache-clear
155 values-type-intersection-cache-clear))
156 (funcall (symbol-function sym))))
159 ;;; Like TYPE-OF, only we return a CTYPE structure instead of a type
160 ;;; specifier, and we try to return the type most useful for type
161 ;;; checking, rather than trying to come up with the one that the user
162 ;;; might find most informative.
163 (declaim (ftype (function (t) ctype) ctype-of))
164 (defun-cached (ctype-of
165 :hash-function (lambda (x) (logand (sxhash x) #x1FF))
167 :init-wrapper !cold-init-forms)
171 (if (funcallable-instance-p x)
173 (extract-function-type x)))
175 (make-member-type :members (list x)))
177 (let* ((num (if (complexp x) (realpart x) x))
178 (res (make-numeric-type
179 :class (etypecase num
183 :format (if (floatp num)
184 (float-format-name num)
187 (setf (numeric-type-complexp res) :complex)
188 (let ((imag (imagpart x)))
189 (setf (numeric-type-low res) (min num imag))
190 (setf (numeric-type-high res) (max num imag))))
192 (setf (numeric-type-low res) num)
193 (setf (numeric-type-high res) num)))
196 (let ((etype (specifier-type (array-element-type x))))
197 (make-array-type :dimensions (array-dimensions x)
198 :complexp (not (typep x 'simple-array))
200 :specialized-element-type etype)))
202 (make-cons-type *universal-type* *universal-type*))
204 (sb!xc:class-of x))))
206 ;;; Clear this cache on GC so that we don't hold onto too much garbage.
207 (pushnew 'ctype-of-cache-clear *before-gc-hooks*)
209 (!defun-from-collected-cold-init-forms !target-type-cold-init)