Make INFO's compiler-macro more forgiving.
[sbcl.git] / src / code / coerce.lisp
blobb245479b89993f00f2adf1271cee124c9a34d5f5
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 (symbol)
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 symbol)))
77 (acond ((macro/special-guard-fun-p def)
78 (error (if (eq it :special)
79 "~S names a special operator." "~S names a macro.")
80 symbol))
81 (t def))))
83 (defun coerce-to-fun (object)
84 ;; (Unlike the other COERCE-TO-FOOs, this one isn't inline, because
85 ;; it's so big and because optimizing away the outer ETYPECASE
86 ;; doesn't seem to buy us that much anyway.)
87 (etypecase object
88 (function object)
89 (symbol
90 (coerce-symbol-to-fun object))
91 (list
92 (case (first object)
93 (setf
94 (fdefinition object))
95 (lambda
96 (eval object))
98 (error 'simple-type-error
99 :datum object
100 :expected-type '(or symbol
101 ;; KLUDGE: ANSI wants us to
102 ;; return a TYPE-ERROR here, and
103 ;; a TYPE-ERROR is supposed to
104 ;; describe the expected type,
105 ;; but it's not obvious how to
106 ;; describe the coerceable cons
107 ;; types, so we punt and just say
108 ;; CONS. -- WHN 20000503
109 cons)
110 :format-control "~S can't be coerced to a function."
111 :format-arguments (list object)))))))
113 (defun coerce-to-list (object)
114 (seq-dispatch object
115 object
116 (vector-to-list* object)
117 (sequence-to-list object)))
119 (defun coerce-to-vector (object output-type-spec)
120 (etypecase object
121 (list (list-to-vector* object output-type-spec))
122 (vector (vector-to-vector* object output-type-spec))))
124 ;;; old working version
125 (defun coerce (object output-type-spec)
126 #!+sb-doc
127 "Coerce the Object to an object of type Output-Type-Spec."
128 (flet ((coerce-error ()
129 (/show0 "entering COERCE-ERROR")
130 (error 'simple-type-error
131 :format-control "~S can't be converted to type ~S."
132 :format-arguments (list object output-type-spec)
133 :datum object
134 :expected-type output-type-spec)))
135 (let ((type (specifier-type output-type-spec)))
136 (cond
137 ((%typep object output-type-spec)
138 object)
139 ((eq type *empty-type*)
140 (coerce-error))
141 ((type= type (specifier-type 'character))
142 (character object))
143 ((numberp object)
144 (cond
145 ((csubtypep type (specifier-type 'single-float))
146 (let ((res (%single-float object)))
147 (unless (typep res output-type-spec)
148 (coerce-error))
149 res))
150 ((csubtypep type (specifier-type 'double-float))
151 (let ((res (%double-float object)))
152 (unless (typep res output-type-spec)
153 (coerce-error))
154 res))
155 #!+long-float
156 ((csubtypep type (specifier-type 'long-float))
157 (let ((res (%long-float object)))
158 (unless (typep res output-type-spec)
159 (coerce-error))
160 res))
161 ((csubtypep type (specifier-type 'float))
162 (let ((res (%single-float object)))
163 (unless (typep res output-type-spec)
164 (coerce-error))
165 res))
167 (let ((res
168 (cond
169 ((csubtypep type (specifier-type '(complex single-float)))
170 (complex (%single-float (realpart object))
171 (%single-float (imagpart object))))
172 ((csubtypep type (specifier-type '(complex double-float)))
173 (complex (%double-float (realpart object))
174 (%double-float (imagpart object))))
175 #!+long-float
176 ((csubtypep type (specifier-type '(complex long-float)))
177 (complex (%long-float (realpart object))
178 (%long-float (imagpart object))))
179 ((csubtypep type (specifier-type '(complex float)))
180 (complex (%single-float (realpart object))
181 (%single-float (imagpart object))))
182 ((and (typep object 'rational) ; TODO jmoringe unreachable?
183 (csubtypep type (specifier-type '(complex float))))
184 ;; Perhaps somewhat surprisingly, ANSI specifies
185 ;; that (COERCE FOO 'FLOAT) is a SINGLE-FLOAT,
186 ;; not dispatching on
187 ;; *READ-DEFAULT-FLOAT-FORMAT*. By analogy, we
188 ;; do the same for complex numbers. -- CSR,
189 ;; 2002-08-06
190 (complex (%single-float object)))
191 ((csubtypep type (specifier-type 'complex))
192 (complex object))
194 (coerce-error)))))
195 ;; If RES has the wrong type, that means that rule of
196 ;; canonical representation for complex rationals was
197 ;; invoked. According to the Hyperspec, (coerce 7/2
198 ;; 'complex) returns 7/2. Thus, if the object was a
199 ;; rational, there is no error here.
200 (unless (or (typep res output-type-spec)
201 (rationalp object))
202 (coerce-error))
203 res))))
204 ((csubtypep type (specifier-type 'list))
205 (if (vectorp object)
206 (cond
207 ((type= type (specifier-type 'list))
208 (vector-to-list* object))
209 ((type= type (specifier-type 'null))
210 (if (= (length object) 0)
211 'nil
212 (sequence-type-length-mismatch-error type
213 (length object))))
214 ((cons-type-p type)
215 (multiple-value-bind (min exactp)
216 (sb!kernel::cons-type-length-info type)
217 (let ((length (length object)))
218 (if exactp
219 (unless (= length min)
220 (sequence-type-length-mismatch-error type length))
221 (unless (>= length min)
222 (sequence-type-length-mismatch-error type length)))
223 (vector-to-list* object))))
224 (t (sequence-type-too-hairy (type-specifier type))))
225 (if (sequencep object)
226 (cond
227 ((type= type (specifier-type 'list))
228 (sb!sequence:make-sequence-like
229 nil (length object) :initial-contents object))
230 ((type= type (specifier-type 'null))
231 (if (= (length object) 0)
232 'nil
233 (sequence-type-length-mismatch-error type
234 (length object))))
235 ((cons-type-p type)
236 (multiple-value-bind (min exactp)
237 (sb!kernel::cons-type-length-info type)
238 (let ((length (length object)))
239 (if exactp
240 (unless (= length min)
241 (sequence-type-length-mismatch-error type length))
242 (unless (>= length min)
243 (sequence-type-length-mismatch-error type length)))
244 (sb!sequence:make-sequence-like
245 nil length :initial-contents object))))
246 (t (sequence-type-too-hairy (type-specifier type))))
247 (coerce-error))))
248 ((csubtypep type (specifier-type 'vector))
249 (typecase object
250 ;; FOO-TO-VECTOR* go through MAKE-SEQUENCE, so length
251 ;; errors are caught there. -- CSR, 2002-10-18
252 (list (list-to-vector* object output-type-spec))
253 (vector (vector-to-vector* object output-type-spec))
254 (sequence (sequence-to-vector* object output-type-spec))
256 (coerce-error))))
257 ((and (csubtypep type (specifier-type 'sequence))
258 (find-class output-type-spec nil))
259 (let ((prototype (sb!mop:class-prototype
260 (sb!pcl:ensure-class-finalized
261 (find-class output-type-spec)))))
262 (sb!sequence:make-sequence-like
263 prototype (length object) :initial-contents object)))
264 ((csubtypep type (specifier-type 'function))
265 (coerce-to-fun object))
267 (coerce-error))))))
269 ;;; new version, which seems as though it should be better, but which
270 ;;; does not yet work
271 #+nil
272 (defun coerce (object output-type-spec)
273 #!+sb-doc
274 "Coerces the Object to an object of type Output-Type-Spec."
275 (flet ((coerce-error ()
276 (error 'simple-type-error
277 :format-control "~S can't be converted to type ~S."
278 :format-arguments (list object output-type-spec)))
279 (check-result (result)
280 #!+high-security (aver (typep result output-type-spec))
281 result))
282 (let ((type (specifier-type output-type-spec)))
283 (cond
284 ((%typep object output-type-spec)
285 object)
286 ((eq type *empty-type*)
287 (coerce-error))
288 ((csubtypep type (specifier-type 'character))
289 (character object))
290 ((csubtypep type (specifier-type 'function))
291 (coerce-to-fun object))
292 ((numberp object)
293 (let ((res
294 (cond
295 ((csubtypep type (specifier-type 'single-float))
296 (%single-float object))
297 ((csubtypep type (specifier-type 'double-float))
298 (%double-float object))
299 #!+long-float
300 ((csubtypep type (specifier-type 'long-float))
301 (%long-float object))
302 ((csubtypep type (specifier-type 'float))
303 (%single-float object))
304 ((csubtypep type (specifier-type '(complex single-float)))
305 (complex (%single-float (realpart object))
306 (%single-float (imagpart object))))
307 ((csubtypep type (specifier-type '(complex double-float)))
308 (complex (%double-float (realpart object))
309 (%double-float (imagpart object))))
310 #!+long-float
311 ((csubtypep type (specifier-type '(complex long-float)))
312 (complex (%long-float (realpart object))
313 (%long-float (imagpart object))))
314 ((csubtypep type (specifier-type 'complex))
315 (complex object))
317 (coerce-error)))))
318 ;; If RES has the wrong type, that means that rule of
319 ;; canonical representation for complex rationals was
320 ;; invoked. According to the ANSI spec, (COERCE 7/2
321 ;; 'COMPLEX) returns 7/2. Thus, if the object was a
322 ;; rational, there is no error here.
323 (unless (or (typep res output-type-spec) (rationalp object))
324 (coerce-error))
325 res))
326 ((csubtypep type (specifier-type 'list))
327 (coerce-to-list object))
328 ((csubtypep type (specifier-type 'string))
329 (check-result (coerce-to-simple-string object)))
330 ((csubtypep type (specifier-type 'bit-vector))
331 (check-result (coerce-to-bit-vector object)))
332 ((csubtypep type (specifier-type 'vector))
333 (check-result (coerce-to-vector object output-type-spec)))
335 (coerce-error))))))