1 ;;;; COERCE and related code
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!IMPL")
14 (macrolet ((def (name result access src-type
&optional typep
)
15 `(defun ,name
(object ,@(if typep
'(type) ()))
16 (declare (type ,(ecase src-type
19 (:sequence
'sequence
)) object
))
20 (do* ((index 0 (1+ index
))
21 (length (length object
))
24 ((>= index length
) result
)
25 (declare (fixnum length index
))
26 (declare (type vector result
))
27 (setf (,access result index
)
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
)
36 (def vector-to-vector
* (make-sequence type length
)
39 (def sequence-to-vector
* (make-sequence type length
)
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 (defvar *offending-datum
*); FIXME: Remove after debugging COERCE.
55 ;;; These are used both by the full DEFUN function and by various
56 ;;; optimization transforms in the constant-OUTPUT-TYPE-SPEC case.
58 ;;; Most of them are INLINE so that they can be optimized when the
59 ;;; argument type is known. It might be better to do this with
60 ;;; DEFTRANSFORMs, though.
61 (declaim (inline coerce-to-list
))
62 (declaim (inline coerce-to-vector
))
63 (defun coerce-to-fun (object)
64 ;; (Unlike the other COERCE-TO-FOOs, this one isn't inline, because
65 ;; it's so big and because optimizing away the outer ETYPECASE
66 ;; doesn't seem to buy us that much anyway.)
69 ;; ANSI lets us return ordinary errors (non-TYPE-ERRORs) here.
70 (cond ((macro-function object
)
71 (error "~S names a macro." object
))
72 ((special-operator-p object
)
73 (error "~S is a special operator." object
))
74 (t (fdefinition object
))))
80 ;; FIXME: If we go to a compiler-only implementation, this can
81 ;; become COMPILE instead of EVAL, which seems nicer to me.
82 (eval `(function ,object
)))
84 (deprecation-warning 'instance-lambda
'lambda
)
85 (eval `(function ,object
)))
87 (error 'simple-type-error
89 :expected-type
'(or symbol
90 ;; KLUDGE: ANSI wants us to
91 ;; return a TYPE-ERROR here, and
92 ;; a TYPE-ERROR is supposed to
93 ;; describe the expected type,
94 ;; but it's not obvious how to
95 ;; describe the coerceable cons
96 ;; types, so we punt and just say
97 ;; CONS. -- WHN 20000503
99 :format-control
"~S can't be coerced to a function."
100 :format-arguments
(list object
)))))))
102 (defun coerce-to-list (object)
104 (vector (vector-to-list* object
))))
106 (defun coerce-to-vector (object output-type-spec
)
108 (list (list-to-vector* object output-type-spec
))
109 (vector (vector-to-vector* object output-type-spec
))))
111 ;;; old working version
112 (defun coerce (object output-type-spec
)
114 "Coerce the Object to an object of type Output-Type-Spec."
115 (flet ((coerce-error ()
116 (/show0
"entering COERCE-ERROR")
117 (error 'simple-type-error
118 :format-control
"~S can't be converted to type ~S."
119 :format-arguments
(list object output-type-spec
)
121 :expected-type output-type-spec
)))
122 (let ((type (specifier-type output-type-spec
)))
124 ((%typep object output-type-spec
)
126 ((eq type
*empty-type
*)
128 ((csubtypep type
(specifier-type 'character
))
132 ((csubtypep type
(specifier-type 'single-float
))
133 (let ((res (%single-float object
)))
134 (unless (typep res output-type-spec
)
137 ((csubtypep type
(specifier-type 'double-float
))
138 (let ((res (%double-float object
)))
139 (unless (typep res output-type-spec
)
143 ((csubtypep type
(specifier-type 'long-float
))
144 (let ((res (%long-float object
)))
145 (unless (typep res output-type-spec
)
148 ((csubtypep type
(specifier-type 'float
))
149 (let ((res (%single-float object
)))
150 (unless (typep res output-type-spec
)
156 ((csubtypep type
(specifier-type '(complex single-float
)))
157 (complex (%single-float
(realpart object
))
158 (%single-float
(imagpart object
))))
159 ((csubtypep type
(specifier-type '(complex double-float
)))
160 (complex (%double-float
(realpart object
))
161 (%double-float
(imagpart object
))))
163 ((csubtypep type
(specifier-type '(complex long-float
)))
164 (complex (%long-float
(realpart object
))
165 (%long-float
(imagpart object
))))
166 ((csubtypep type
(specifier-type '(complex float
)))
167 (complex (%single-float
(realpart object
))
168 (%single-float
(imagpart object
))))
169 ((and (typep object
'rational
)
170 (csubtypep type
(specifier-type '(complex float
))))
171 ;; Perhaps somewhat surprisingly, ANSI specifies
172 ;; that (COERCE FOO 'FLOAT) is a SINGLE-FLOAT,
173 ;; not dispatching on
174 ;; *READ-DEFAULT-FLOAT-FORMAT*. By analogy, we
175 ;; do the same for complex numbers. -- CSR,
177 (complex (%single-float object
)))
178 ((csubtypep type
(specifier-type 'complex
))
182 ;; If RES has the wrong type, that means that rule of
183 ;; canonical representation for complex rationals was
184 ;; invoked. According to the Hyperspec, (coerce 7/2
185 ;; 'complex) returns 7/2. Thus, if the object was a
186 ;; rational, there is no error here.
187 (unless (or (typep res output-type-spec
)
191 ((csubtypep type
(specifier-type 'list
))
194 ((type= type
(specifier-type 'list
))
195 (vector-to-list* object
))
196 ((type= type
(specifier-type 'null
))
197 (if (= (length object
) 0)
199 (sequence-type-length-mismatch-error type
202 (multiple-value-bind (min exactp
)
203 (sb!kernel
::cons-type-length-info type
)
204 (let ((length (length object
)))
206 (unless (= length min
)
207 (sequence-type-length-mismatch-error type length
))
208 (unless (>= length min
)
209 (sequence-type-length-mismatch-error type length
)))
210 (vector-to-list* object
))))
211 (t (sequence-type-too-hairy (type-specifier type
))))
212 (if (sequencep object
)
214 ((type= type
(specifier-type 'list
))
215 (sb!sequence
:make-sequence-like
216 nil
(length object
) :initial-contents object
))
217 ((type= type
(specifier-type 'null
))
218 (if (= (length object
) 0)
220 (sequence-type-length-mismatch-error type
223 (multiple-value-bind (min exactp
)
224 (sb!kernel
::cons-type-length-info type
)
225 (let ((length (length object
)))
227 (unless (= length min
)
228 (sequence-type-length-mismatch-error type length
))
229 (unless (>= length min
)
230 (sequence-type-length-mismatch-error type length
)))
231 (sb!sequence
:make-sequence-like
232 nil length
:initial-contents object
))))
233 (t (sequence-type-too-hairy (type-specifier type
))))
235 ((csubtypep type
(specifier-type 'vector
))
237 ;; FOO-TO-VECTOR* go through MAKE-SEQUENCE, so length
238 ;; errors are caught there. -- CSR, 2002-10-18
239 (list (list-to-vector* object output-type-spec
))
240 (vector (vector-to-vector* object output-type-spec
))
241 (sequence (sequence-to-vector* object output-type-spec
))
244 ((and (csubtypep type
(specifier-type 'sequence
))
245 (find-class output-type-spec nil
))
246 (let ((class (find-class output-type-spec
)))
247 (sb!sequence
:make-sequence-like
248 (sb!mop
:class-prototype class
)
249 (length object
) :initial-contents object
)))
250 ((csubtypep type
(specifier-type 'function
))
251 (when (and (legal-fun-name-p object
)
252 (not (fboundp object
)))
253 (error 'simple-type-error
255 ;; FIXME: SATISFIES FBOUNDP is a kinda bizarre broken
256 ;; type specifier, since the set of values it describes
257 ;; isn't in general constant in time. Maybe we could
258 ;; find a better way of expressing this error? (Maybe
259 ;; with the UNDEFINED-FUNCTION condition?)
260 :expected-type
'(satisfies fboundp
)
261 :format-control
"~S isn't fbound."
262 :format-arguments
(list object
)))
263 (when (and (symbolp object
)
264 (sb!xc
:macro-function object
))
265 (error 'simple-type-error
267 :expected-type
'(not (satisfies sb
!xc
:macro-function
))
268 :format-control
"~S is a macro."
269 :format-arguments
(list object
)))
270 (when (and (symbolp object
)
271 (special-operator-p object
))
272 (error 'simple-type-error
274 :expected-type
'(not (satisfies special-operator-p
))
275 :format-control
"~S is a special operator."
276 :format-arguments
(list object
)))
281 ;;; new version, which seems as though it should be better, but which
282 ;;; does not yet work
284 (defun coerce (object output-type-spec
)
286 "Coerces the Object to an object of type Output-Type-Spec."
287 (flet ((coerce-error ()
288 (error 'simple-type-error
289 :format-control
"~S can't be converted to type ~S."
290 :format-arguments
(list object output-type-spec
)))
291 (check-result (result)
292 #!+high-security
(aver (typep result output-type-spec
))
294 (let ((type (specifier-type output-type-spec
)))
296 ((%typep object output-type-spec
)
298 ((eq type
*empty-type
*)
300 ((csubtypep type
(specifier-type 'character
))
302 ((csubtypep type
(specifier-type 'function
))
303 (coerce-to-fun object
))
307 ((csubtypep type
(specifier-type 'single-float
))
308 (%single-float object
))
309 ((csubtypep type
(specifier-type 'double-float
))
310 (%double-float object
))
312 ((csubtypep type
(specifier-type 'long-float
))
313 (%long-float object
))
314 ((csubtypep type
(specifier-type 'float
))
315 (%single-float object
))
316 ((csubtypep type
(specifier-type '(complex single-float
)))
317 (complex (%single-float
(realpart object
))
318 (%single-float
(imagpart object
))))
319 ((csubtypep type
(specifier-type '(complex double-float
)))
320 (complex (%double-float
(realpart object
))
321 (%double-float
(imagpart object
))))
323 ((csubtypep type
(specifier-type '(complex long-float
)))
324 (complex (%long-float
(realpart object
))
325 (%long-float
(imagpart object
))))
326 ((csubtypep type
(specifier-type 'complex
))
330 ;; If RES has the wrong type, that means that rule of
331 ;; canonical representation for complex rationals was
332 ;; invoked. According to the ANSI spec, (COERCE 7/2
333 ;; 'COMPLEX) returns 7/2. Thus, if the object was a
334 ;; rational, there is no error here.
335 (unless (or (typep res output-type-spec
) (rationalp object
))
338 ((csubtypep type
(specifier-type 'list
))
339 (coerce-to-list object
))
340 ((csubtypep type
(specifier-type 'string
))
341 (check-result (coerce-to-simple-string object
)))
342 ((csubtypep type
(specifier-type 'bit-vector
))
343 (check-result (coerce-to-bit-vector object
)))
344 ((csubtypep type
(specifier-type 'vector
))
345 (check-result (coerce-to-vector object output-type-spec
)))