fix APROPOS/APROPOS-LIST and inherited symbols
[sbcl.git] / src / code / coerce.lisp
blob0fd9d59b9c1a1707009112fc1ce8d98cbb017cd9
1 ;;;; COERCE and related code
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.
12 (in-package "SB!IMPL")
14 (macrolet ((def (name result access src-type &optional typep)
15 `(defun ,name (object ,@(if typep '(type) ()))
16 (declare (type ,(ecase src-type
17 (:list 'list)
18 (:vector 'vector)
19 (:sequence 'sequence)) object))
20 (do* ((index 0 (1+ index))
21 (length (length object))
22 (result ,result)
23 (in-object object))
24 ((>= index length) result)
25 (declare (fixnum length index))
26 (declare (type vector result))
27 (setf (,access result index)
28 ,(ecase src-type
29 (:list '(pop in-object))
30 (:vector '(aref in-object index))
31 (:sequence '(elt in-object index))))))))
33 (def list-to-vector* (make-sequence type length)
34 aref :list t)
36 (def vector-to-vector* (make-sequence type length)
37 aref :vector t)
39 (def sequence-to-vector* (make-sequence type length)
40 aref :sequence t))
42 (defun vector-to-list* (object)
43 (declare (type vector object))
44 (let ((result (list nil))
45 (length (length object)))
46 (declare (fixnum length))
47 (do ((index 0 (1+ index))
48 (splice result (cdr splice)))
49 ((>= index length) (cdr result))
50 (declare (fixnum index))
51 (rplacd splice (list (aref object index))))))
53 (defun sequence-to-list (sequence)
54 (declare (type sequence sequence))
55 (let* ((result (list nil))
56 (splice result))
57 (sb!sequence:dosequence (i sequence)
58 (rplacd splice (list i))
59 (setf splice (cdr splice)))
60 (cdr result)))
62 ;;; These are used both by the full DEFUN function and by various
63 ;;; optimization transforms in the constant-OUTPUT-TYPE-SPEC case.
64 ;;;
65 ;;; Most of them are INLINE so that they can be optimized when the
66 ;;; argument type is known. It might be better to do this with
67 ;;; DEFTRANSFORMs, though.
68 (declaim (inline coerce-to-list))
69 (declaim (inline coerce-to-vector))
71 (defun coerce-symbol-to-fun (object)
72 ;; FIXME? I would think to use SYMBOL-FUNCTION here which does not strip off
73 ;; encapsulations. But Stas wrote FDEFINITION so ...
74 ;; [Also note, we won't encapsulate a macro or special-form, so this
75 ;; introspective technique to decide what kind something is works either way]
76 (let* ((def (fdefinition object))
77 (widetag (fun-subtype def)))
78 (cond ((and (eq widetag sb!vm:closure-header-widetag)
79 (eq (%closure-fun def)
80 (load-time-value
81 ;; pick a macro, any macro...
82 (%closure-fun (symbol-function 'with-unique-names))
83 t)))
84 (error "~S names a macro." object))
85 ((and (eq widetag sb!vm:simple-fun-header-widetag)
86 (let ((name (%simple-fun-name def)))
87 (and (listp name) (eq (car name) 'special-operator))))
88 (error "~S names a special operator." object))
90 def))))
92 (defun coerce-to-fun (object)
93 ;; (Unlike the other COERCE-TO-FOOs, this one isn't inline, because
94 ;; it's so big and because optimizing away the outer ETYPECASE
95 ;; doesn't seem to buy us that much anyway.)
96 (etypecase object
97 (function object)
98 (symbol
99 (coerce-symbol-to-fun object))
100 (list
101 (case (first object)
102 (setf
103 (fdefinition object))
104 (lambda
105 (eval object))
107 (error 'simple-type-error
108 :datum object
109 :expected-type '(or symbol
110 ;; KLUDGE: ANSI wants us to
111 ;; return a TYPE-ERROR here, and
112 ;; a TYPE-ERROR is supposed to
113 ;; describe the expected type,
114 ;; but it's not obvious how to
115 ;; describe the coerceable cons
116 ;; types, so we punt and just say
117 ;; CONS. -- WHN 20000503
118 cons)
119 :format-control "~S can't be coerced to a function."
120 :format-arguments (list object)))))))
122 (defun coerce-to-list (object)
123 (seq-dispatch object
124 object
125 (vector-to-list* object)
126 (sequence-to-list object)))
128 (defun coerce-to-vector (object output-type-spec)
129 (etypecase object
130 (list (list-to-vector* object output-type-spec))
131 (vector (vector-to-vector* object output-type-spec))))
133 ;;; old working version
134 (defun coerce (object output-type-spec)
135 #!+sb-doc
136 "Coerce the Object to an object of type Output-Type-Spec."
137 (flet ((coerce-error ()
138 (/show0 "entering COERCE-ERROR")
139 (error 'simple-type-error
140 :format-control "~S can't be converted to type ~S."
141 :format-arguments (list object output-type-spec)
142 :datum object
143 :expected-type output-type-spec)))
144 (let ((type (specifier-type output-type-spec)))
145 (cond
146 ((%typep object output-type-spec)
147 object)
148 ((eq type *empty-type*)
149 (coerce-error))
150 ((type= type (specifier-type 'character))
151 (character object))
152 ((numberp object)
153 (cond
154 ((csubtypep type (specifier-type 'single-float))
155 (let ((res (%single-float object)))
156 (unless (typep res output-type-spec)
157 (coerce-error))
158 res))
159 ((csubtypep type (specifier-type 'double-float))
160 (let ((res (%double-float object)))
161 (unless (typep res output-type-spec)
162 (coerce-error))
163 res))
164 #!+long-float
165 ((csubtypep type (specifier-type 'long-float))
166 (let ((res (%long-float object)))
167 (unless (typep res output-type-spec)
168 (coerce-error))
169 res))
170 ((csubtypep type (specifier-type 'float))
171 (let ((res (%single-float object)))
172 (unless (typep res output-type-spec)
173 (coerce-error))
174 res))
176 (let ((res
177 (cond
178 ((csubtypep type (specifier-type '(complex single-float)))
179 (complex (%single-float (realpart object))
180 (%single-float (imagpart object))))
181 ((csubtypep type (specifier-type '(complex double-float)))
182 (complex (%double-float (realpart object))
183 (%double-float (imagpart object))))
184 #!+long-float
185 ((csubtypep type (specifier-type '(complex long-float)))
186 (complex (%long-float (realpart object))
187 (%long-float (imagpart object))))
188 ((csubtypep type (specifier-type '(complex float)))
189 (complex (%single-float (realpart object))
190 (%single-float (imagpart object))))
191 ((and (typep object 'rational) ; TODO jmoringe unreachable?
192 (csubtypep type (specifier-type '(complex float))))
193 ;; Perhaps somewhat surprisingly, ANSI specifies
194 ;; that (COERCE FOO 'FLOAT) is a SINGLE-FLOAT,
195 ;; not dispatching on
196 ;; *READ-DEFAULT-FLOAT-FORMAT*. By analogy, we
197 ;; do the same for complex numbers. -- CSR,
198 ;; 2002-08-06
199 (complex (%single-float object)))
200 ((csubtypep type (specifier-type 'complex))
201 (complex object))
203 (coerce-error)))))
204 ;; If RES has the wrong type, that means that rule of
205 ;; canonical representation for complex rationals was
206 ;; invoked. According to the Hyperspec, (coerce 7/2
207 ;; 'complex) returns 7/2. Thus, if the object was a
208 ;; rational, there is no error here.
209 (unless (or (typep res output-type-spec)
210 (rationalp object))
211 (coerce-error))
212 res))))
213 ((csubtypep type (specifier-type 'list))
214 (if (vectorp object)
215 (cond
216 ((type= type (specifier-type 'list))
217 (vector-to-list* object))
218 ((type= type (specifier-type 'null))
219 (if (= (length object) 0)
220 'nil
221 (sequence-type-length-mismatch-error type
222 (length object))))
223 ((cons-type-p type)
224 (multiple-value-bind (min exactp)
225 (sb!kernel::cons-type-length-info type)
226 (let ((length (length object)))
227 (if exactp
228 (unless (= length min)
229 (sequence-type-length-mismatch-error type length))
230 (unless (>= length min)
231 (sequence-type-length-mismatch-error type length)))
232 (vector-to-list* object))))
233 (t (sequence-type-too-hairy (type-specifier type))))
234 (if (sequencep object)
235 (cond
236 ((type= type (specifier-type 'list))
237 (sb!sequence:make-sequence-like
238 nil (length object) :initial-contents object))
239 ((type= type (specifier-type 'null))
240 (if (= (length object) 0)
241 'nil
242 (sequence-type-length-mismatch-error type
243 (length object))))
244 ((cons-type-p type)
245 (multiple-value-bind (min exactp)
246 (sb!kernel::cons-type-length-info type)
247 (let ((length (length object)))
248 (if exactp
249 (unless (= length min)
250 (sequence-type-length-mismatch-error type length))
251 (unless (>= length min)
252 (sequence-type-length-mismatch-error type length)))
253 (sb!sequence:make-sequence-like
254 nil length :initial-contents object))))
255 (t (sequence-type-too-hairy (type-specifier type))))
256 (coerce-error))))
257 ((csubtypep type (specifier-type 'vector))
258 (typecase object
259 ;; FOO-TO-VECTOR* go through MAKE-SEQUENCE, so length
260 ;; errors are caught there. -- CSR, 2002-10-18
261 (list (list-to-vector* object output-type-spec))
262 (vector (vector-to-vector* object output-type-spec))
263 (sequence (sequence-to-vector* object output-type-spec))
265 (coerce-error))))
266 ((and (csubtypep type (specifier-type 'sequence))
267 (find-class output-type-spec nil))
268 (let ((prototype (sb!mop:class-prototype
269 (sb!pcl:ensure-class-finalized
270 (find-class output-type-spec)))))
271 (sb!sequence:make-sequence-like
272 prototype (length object) :initial-contents object)))
273 ((csubtypep type (specifier-type 'function))
274 (coerce-to-fun object))
276 (coerce-error))))))
278 ;;; new version, which seems as though it should be better, but which
279 ;;; does not yet work
280 #+nil
281 (defun coerce (object output-type-spec)
282 #!+sb-doc
283 "Coerces the Object to an object of type Output-Type-Spec."
284 (flet ((coerce-error ()
285 (error 'simple-type-error
286 :format-control "~S can't be converted to type ~S."
287 :format-arguments (list object output-type-spec)))
288 (check-result (result)
289 #!+high-security (aver (typep result output-type-spec))
290 result))
291 (let ((type (specifier-type output-type-spec)))
292 (cond
293 ((%typep object output-type-spec)
294 object)
295 ((eq type *empty-type*)
296 (coerce-error))
297 ((csubtypep type (specifier-type 'character))
298 (character object))
299 ((csubtypep type (specifier-type 'function))
300 (coerce-to-fun object))
301 ((numberp object)
302 (let ((res
303 (cond
304 ((csubtypep type (specifier-type 'single-float))
305 (%single-float object))
306 ((csubtypep type (specifier-type 'double-float))
307 (%double-float object))
308 #!+long-float
309 ((csubtypep type (specifier-type 'long-float))
310 (%long-float object))
311 ((csubtypep type (specifier-type 'float))
312 (%single-float object))
313 ((csubtypep type (specifier-type '(complex single-float)))
314 (complex (%single-float (realpart object))
315 (%single-float (imagpart object))))
316 ((csubtypep type (specifier-type '(complex double-float)))
317 (complex (%double-float (realpart object))
318 (%double-float (imagpart object))))
319 #!+long-float
320 ((csubtypep type (specifier-type '(complex long-float)))
321 (complex (%long-float (realpart object))
322 (%long-float (imagpart object))))
323 ((csubtypep type (specifier-type 'complex))
324 (complex object))
326 (coerce-error)))))
327 ;; If RES has the wrong type, that means that rule of
328 ;; canonical representation for complex rationals was
329 ;; invoked. According to the ANSI spec, (COERCE 7/2
330 ;; 'COMPLEX) returns 7/2. Thus, if the object was a
331 ;; rational, there is no error here.
332 (unless (or (typep res output-type-spec) (rationalp object))
333 (coerce-error))
334 res))
335 ((csubtypep type (specifier-type 'list))
336 (coerce-to-list object))
337 ((csubtypep type (specifier-type 'string))
338 (check-result (coerce-to-simple-string object)))
339 ((csubtypep type (specifier-type 'bit-vector))
340 (check-result (coerce-to-bit-vector object)))
341 ((csubtypep type (specifier-type 'vector))
342 (check-result (coerce-to-vector object output-type-spec)))
344 (coerce-error))))))