1 ;;;; This software is part of the SBCL system. See the README file for
4 ;;;; This software is derived from the CMU CL system, which was
5 ;;;; written at Carnegie Mellon University and released into the
6 ;;;; public domain. The software is in the public domain and is
7 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
8 ;;;; files for more information.
10 (in-package "SB!KERNEL")
12 ;;; the actual TYPEP engine. The compiler only generates calls to this
13 ;;; function when it can't figure out anything more intelligent to do.
14 (defun %typep (object specifier)
16 (if (ctype-p specifier)
18 (specifier-type specifier))))
19 (defun %%typep (object type)
20 (declare (type ctype type))
23 (ecase (named-type-name type)
28 (let ((num (if (complexp object) (realpart object) object)))
29 (ecase (numeric-type-class type)
30 (integer (integerp num))
31 (rational (rationalp num))
33 (ecase (numeric-type-format type)
34 (short-float (typep num 'short-float))
35 (single-float (typep num 'single-float))
36 (double-float (typep num 'double-float))
37 (long-float (typep num 'long-float))
38 ((nil) (floatp num))))
40 #!-negative-zero-is-not-zero
41 (flet ((bound-test (val)
42 (let ((low (numeric-type-low type))
43 (high (numeric-type-high type)))
44 (and (cond ((null low) t)
45 ((listp low) (> val (car low)))
48 ((listp high) (< val (car high)))
49 (t (<= val high)))))))
50 (ecase (numeric-type-complexp type)
53 (and (complexp object)
54 (bound-test (realpart object))
55 (bound-test (imagpart object))))
57 (and (not (complexp object))
58 (bound-test object)))))
59 #!+negative-zero-is-not-zero
60 (labels ((signed-> (x y)
61 (if (and (zerop x) (zerop y) (floatp x) (floatp y))
62 (> (float-sign x) (float-sign y))
65 (if (and (zerop x) (zerop y) (floatp x) (floatp y))
66 (>= (float-sign x) (float-sign y))
69 (let ((low (numeric-type-low type))
70 (high (numeric-type-high type)))
71 (and (cond ((null low) t)
73 (signed-> val (car low)))
78 (signed-> (car high) val))
80 (signed->= high val)))))))
81 (ecase (numeric-type-complexp type)
84 (and (complexp object)
85 (bound-test (realpart object))
86 (bound-test (imagpart object))))
88 (and (not (complexp object))
89 (bound-test object)))))))
92 (ecase (array-type-complexp type)
93 ((t) (not (typep object 'simple-array)))
94 ((nil) (typep object 'simple-array))
96 (or (eq (array-type-dimensions type) '*)
97 (do ((want (array-type-dimensions type) (cdr want))
98 (got (array-dimensions object) (cdr got)))
99 ((and (null want) (null got)) t)
100 (unless (and want got
101 (or (eq (car want) '*)
102 (= (car want) (car got))))
104 (if (unknown-type-p (array-type-element-type type))
105 ;; better to fail this way than to get bogosities like
106 ;; (TYPEP (MAKE-ARRAY 11) '(ARRAY SOME-UNDEFINED-TYPE)) => T
107 (error "~@<unknown element type in array type: ~2I~_~S~:>"
108 (type-specifier type))
110 (or (eq (array-type-element-type type) *wild-type*)
111 (values (type= (array-type-specialized-element-type type)
112 (specifier-type (array-element-type
115 (if (member object (member-type-members type)) t))
117 #+sb-xc-host (ctypep object type)
118 #-sb-xc-host (class-typep (layout-of object) type object))
120 (some (lambda (union-type-type) (%%typep object union-type-type))
121 (union-type-types type)))
123 (every (lambda (intersection-type-type)
124 (%%typep object intersection-type-type))
125 (intersection-type-types type)))
128 (%%typep (car object) (cons-type-car-type type))
129 (%%typep (cdr object) (cons-type-cdr-type type))))
131 ;; dunno how to do this ANSIly -- WHN 19990413
132 #+sb-xc-host (error "stub: %%TYPEP UNKNOWN-TYPE in xcompilation host")
133 ;; Parse it again to make sure it's really undefined.
134 (let ((reparse (specifier-type (unknown-type-specifier type))))
135 (if (typep reparse 'unknown-type)
136 (error "unknown type specifier: ~S"
137 (unknown-type-specifier reparse))
138 (%%typep object reparse))))
140 ;; Now the tricky stuff.
141 (let* ((hairy-spec (hairy-type-specifier type))
142 (symbol (car hairy-spec)))
145 (every (lambda (spec) (%%typep object (specifier-type spec)))
147 ;; Note: it should be safe to skip OR here, because union
148 ;; types can always be represented as UNION-TYPE in general
149 ;; or other CTYPEs in special cases; we never need to use
150 ;; HAIRY-TYPE for them.
152 (unless (proper-list-of-length-p hairy-spec 2)
153 (error "invalid type specifier: ~S" hairy-spec))
154 (not (%%typep object (specifier-type (cadr hairy-spec)))))
156 (unless (proper-list-of-length-p hairy-spec 2)
157 (error "invalid type specifier: ~S" hairy-spec))
158 (values (funcall (symbol-function (cadr hairy-spec)) object))))))
160 (sb!alien-internals:alien-typep object (alien-type-type-alien-type type)))
162 (error "Function types are not a legal argument to TYPEP:~% ~S"
163 (type-specifier type)))))
165 ;;; Do a type test from a class cell, allowing forward reference and
167 (defun class-cell-typep (obj-layout cell object)
168 (let ((class (class-cell-class cell)))
170 (error "The class ~S has not yet been defined." (class-cell-name cell)))
171 (class-typep obj-layout class object)))
173 ;;; Test whether OBJ-LAYOUT is from an instance of CLASS.
174 (defun class-typep (obj-layout class object)
175 (declare (optimize speed))
176 (when (layout-invalid obj-layout)
177 (if (and (typep (sb!xc:class-of object) 'sb!xc:standard-class) object)
178 (setq obj-layout (pcl-check-wrapper-validity-hook object))
179 (error "TYPEP was called on an obsolete object (was class ~S)."
180 (class-proper-name (layout-class obj-layout)))))
181 (let ((layout (class-layout class))
182 (obj-inherits (layout-inherits obj-layout)))
183 (when (layout-invalid layout)
184 (error "The class ~S is currently invalid." class))
185 (or (eq obj-layout layout)
186 (dotimes (i (length obj-inherits) nil)
187 (when (eq (svref obj-inherits i) layout)
190 ;;; to be redefined as PCL::CHECK-WRAPPER-VALIDITY when PCL is loaded
192 ;;; FIXME: should probably be renamed SB!PCL:CHECK-WRAPPER-VALIDITY
193 (defun pcl-check-wrapper-validity-hook (object)