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 (do* ((index 0 (1+ index
))
17 (length (length (the ,(ecase src-type
23 ((= index length
) result
)
24 (declare (fixnum length index
))
25 (setf (,access result index
)
27 (:list
'(pop in-object
))
28 (:vector
'(aref in-object index
))))))))
30 (def list-to-vector
* (make-sequence type length
)
33 (def vector-to-vector
* (make-sequence type length
)
36 (defun vector-to-list* (object)
37 (let ((result (list nil
))
38 (length (length object
)))
39 (declare (fixnum length
))
40 (do ((index 0 (1+ index
))
41 (splice result
(cdr splice
)))
42 ((= index length
) (cdr result
))
43 (declare (fixnum index
))
44 (rplacd splice
(list (aref object index
))))))
46 (defvar *offending-datum
*); FIXME: Remove after debugging COERCE.
48 ;;; These are used both by the full DEFUN function and by various
49 ;;; optimization transforms in the constant-OUTPUT-TYPE-SPEC case.
51 ;;; Most of them are INLINE so that they can be optimized when the
52 ;;; argument type is known. It might be better to do this with
53 ;;; DEFTRANSFORMs, though.
54 (declaim (inline coerce-to-list
))
55 (declaim (inline coerce-to-vector
))
56 (defun coerce-to-fun (object)
57 ;; (Unlike the other COERCE-TO-FOOs, this one isn't inline, because
58 ;; it's so big and because optimizing away the outer ETYPECASE
59 ;; doesn't seem to buy us that much anyway.)
62 ;; ANSI lets us return ordinary errors (non-TYPE-ERRORs) here.
63 (cond ((macro-function object
)
64 (error "~S names a macro." object
))
65 ((special-operator-p object
)
66 (error "~S is a special operator." object
))
67 (t (fdefinition object
))))
72 ((lambda instance-lambda
)
73 ;; FIXME: If we go to a compiler-only implementation, this can
74 ;; become COMPILE instead of EVAL, which seems nicer to me.
75 (eval `(function ,object
)))
77 (error 'simple-type-error
79 :expected-type
'(or symbol
80 ;; KLUDGE: ANSI wants us to
81 ;; return a TYPE-ERROR here, and
82 ;; a TYPE-ERROR is supposed to
83 ;; describe the expected type,
84 ;; but it's not obvious how to
85 ;; describe the coerceable cons
86 ;; types, so we punt and just say
87 ;; CONS. -- WHN 20000503
89 :format-control
"~S can't be coerced to a function."
90 :format-arguments
(list object
)))))))
92 (defun coerce-to-list (object)
94 (vector (vector-to-list* object
))))
96 (defun coerce-to-vector (object output-type-spec
)
98 (list (list-to-vector* object output-type-spec
))
99 (vector (vector-to-vector* object output-type-spec
))))
101 ;;; old working version
102 (defun coerce (object output-type-spec
)
104 "Coerce the Object to an object of type Output-Type-Spec."
105 (flet ((coerce-error ()
106 (/show0
"entering COERCE-ERROR")
107 (error 'simple-type-error
108 :format-control
"~S can't be converted to type ~S."
109 :format-arguments
(list object output-type-spec
))))
110 (let ((type (specifier-type output-type-spec
)))
112 ((%typep object output-type-spec
)
114 ((eq type
*empty-type
*)
116 ((csubtypep type
(specifier-type 'character
))
118 ((csubtypep type
(specifier-type 'function
))
119 (when (and (legal-fun-name-p object
)
120 (not (fboundp object
)))
121 (error 'simple-type-error
123 ;; FIXME: SATISFIES FBOUNDP is a kinda bizarre broken
124 ;; type specifier, since the set of values it describes
125 ;; isn't in general constant in time. Maybe we could
126 ;; find a better way of expressing this error? (Maybe
127 ;; with the UNDEFINED-FUNCTION condition?)
128 :expected-type
'(satisfies fboundp
)
129 :format-control
"~S isn't fbound."
130 :format-arguments
(list object
)))
131 (when (and (symbolp object
)
132 (sb!xc
:macro-function object
))
133 (error 'simple-type-error
135 :expected-type
'(not (satisfies sb
!xc
:macro-function
))
136 :format-control
"~S is a macro."
137 :format-arguments
(list object
)))
138 (when (and (symbolp object
)
139 (special-operator-p object
))
140 (error 'simple-type-error
142 :expected-type
'(not (satisfies special-operator-p
))
143 :format-control
"~S is a special operator."
144 :format-arguments
(list object
)))
148 ((csubtypep type
(specifier-type 'single-float
))
149 (let ((res (%single-float object
)))
150 (unless (typep res output-type-spec
)
153 ((csubtypep type
(specifier-type 'double-float
))
154 (let ((res (%double-float object
)))
155 (unless (typep res output-type-spec
)
159 ((csubtypep type
(specifier-type 'long-float
))
160 (let ((res (%long-float object
)))
161 (unless (typep res output-type-spec
)
164 ((csubtypep type
(specifier-type 'float
))
165 (let ((res (%single-float object
)))
166 (unless (typep res output-type-spec
)
172 ((csubtypep type
(specifier-type '(complex single-float
)))
173 (complex (%single-float
(realpart object
))
174 (%single-float
(imagpart object
))))
175 ((csubtypep type
(specifier-type '(complex double-float
)))
176 (complex (%double-float
(realpart object
))
177 (%double-float
(imagpart object
))))
179 ((csubtypep type
(specifier-type '(complex long-float
)))
180 (complex (%long-float
(realpart object
))
181 (%long-float
(imagpart object
))))
182 ((and (typep object
'rational
)
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,
190 (complex (%single-float object
)))
191 ((csubtypep type
(specifier-type 'complex
))
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
)
204 ((csubtypep type
(specifier-type 'list
))
207 ((type= type
(specifier-type 'list
))
208 (vector-to-list* object
))
209 ((type= type
(specifier-type 'null
))
210 (if (= (length object
) 0)
212 (sequence-type-length-mismatch-error type
215 (multiple-value-bind (min exactp
)
216 (sb!kernel
::cons-type-length-info type
)
217 (let ((length (length object
)))
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
))))
226 ((csubtypep type
(specifier-type 'vector
))
228 ;; FOO-TO-VECTOR* go through MAKE-SEQUENCE, so length
229 ;; errors are caught there. -- CSR, 2002-10-18
230 (list (list-to-vector* object output-type-spec
))
231 (vector (vector-to-vector* object output-type-spec
))
237 ;;; new version, which seems as though it should be better, but which
238 ;;; does not yet work
240 (defun coerce (object output-type-spec
)
242 "Coerces the Object to an object of type Output-Type-Spec."
243 (flet ((coerce-error ()
244 (error 'simple-type-error
245 :format-control
"~S can't be converted to type ~S."
246 :format-arguments
(list object output-type-spec
)))
247 (check-result (result)
248 #!+high-security
(aver (typep result output-type-spec
))
250 (let ((type (specifier-type output-type-spec
)))
252 ((%typep object output-type-spec
)
254 ((eq type
*empty-type
*)
256 ((csubtypep type
(specifier-type 'character
))
258 ((csubtypep type
(specifier-type 'function
))
259 (coerce-to-fun object
))
263 ((csubtypep type
(specifier-type 'single-float
))
264 (%single-float object
))
265 ((csubtypep type
(specifier-type 'double-float
))
266 (%double-float object
))
268 ((csubtypep type
(specifier-type 'long-float
))
269 (%long-float object
))
270 ((csubtypep type
(specifier-type 'float
))
271 (%single-float object
))
272 ((csubtypep type
(specifier-type '(complex single-float
)))
273 (complex (%single-float
(realpart object
))
274 (%single-float
(imagpart object
))))
275 ((csubtypep type
(specifier-type '(complex double-float
)))
276 (complex (%double-float
(realpart object
))
277 (%double-float
(imagpart object
))))
279 ((csubtypep type
(specifier-type '(complex long-float
)))
280 (complex (%long-float
(realpart object
))
281 (%long-float
(imagpart object
))))
282 ((csubtypep type
(specifier-type 'complex
))
286 ;; If RES has the wrong type, that means that rule of
287 ;; canonical representation for complex rationals was
288 ;; invoked. According to the ANSI spec, (COERCE 7/2
289 ;; 'COMPLEX) returns 7/2. Thus, if the object was a
290 ;; rational, there is no error here.
291 (unless (or (typep res output-type-spec
) (rationalp object
))
294 ((csubtypep type
(specifier-type 'list
))
295 (coerce-to-list object
))
296 ((csubtypep type
(specifier-type 'string
))
297 (check-result (coerce-to-simple-string object
)))
298 ((csubtypep type
(specifier-type 'bit-vector
))
299 (check-result (coerce-to-bit-vector object
)))
300 ((csubtypep type
(specifier-type 'vector
))
301 (check-result (coerce-to-vector object output-type-spec
)))