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))))
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 (deprecation-warning 'instance-lambda 'lambda)
78 (eval `(function ,object)))
80 (error 'simple-type-error
82 :expected-type '(or symbol
83 ;; KLUDGE: ANSI wants us to
84 ;; return a TYPE-ERROR here, and
85 ;; a TYPE-ERROR is supposed to
86 ;; describe the expected type,
87 ;; but it's not obvious how to
88 ;; describe the coerceable cons
89 ;; types, so we punt and just say
90 ;; CONS. -- WHN 20000503
92 :format-control "~S can't be coerced to a function."
93 :format-arguments (list object)))))))
95 (defun coerce-to-list (object)
97 (vector (vector-to-list* object))))
99 (defun coerce-to-vector (object output-type-spec)
101 (list (list-to-vector* object output-type-spec))
102 (vector (vector-to-vector* object output-type-spec))))
104 ;;; old working version
105 (defun coerce (object output-type-spec)
107 "Coerce the Object to an object of type Output-Type-Spec."
108 (flet ((coerce-error ()
109 (/show0 "entering COERCE-ERROR")
110 (error 'simple-type-error
111 :format-control "~S can't be converted to type ~S."
112 :format-arguments (list object output-type-spec)
114 :expected-type output-type-spec)))
115 (let ((type (specifier-type output-type-spec)))
117 ((%typep object output-type-spec)
119 ((eq type *empty-type*)
121 ((csubtypep type (specifier-type 'character))
123 ((csubtypep type (specifier-type 'function))
124 (when (and (legal-fun-name-p object)
125 (not (fboundp object)))
126 (error 'simple-type-error
128 ;; FIXME: SATISFIES FBOUNDP is a kinda bizarre broken
129 ;; type specifier, since the set of values it describes
130 ;; isn't in general constant in time. Maybe we could
131 ;; find a better way of expressing this error? (Maybe
132 ;; with the UNDEFINED-FUNCTION condition?)
133 :expected-type '(satisfies fboundp)
134 :format-control "~S isn't fbound."
135 :format-arguments (list object)))
136 (when (and (symbolp object)
137 (sb!xc:macro-function object))
138 (error 'simple-type-error
140 :expected-type '(not (satisfies sb!xc:macro-function))
141 :format-control "~S is a macro."
142 :format-arguments (list object)))
143 (when (and (symbolp object)
144 (special-operator-p object))
145 (error 'simple-type-error
147 :expected-type '(not (satisfies special-operator-p))
148 :format-control "~S is a special operator."
149 :format-arguments (list object)))
153 ((csubtypep type (specifier-type 'single-float))
154 (let ((res (%single-float object)))
155 (unless (typep res output-type-spec)
158 ((csubtypep type (specifier-type 'double-float))
159 (let ((res (%double-float object)))
160 (unless (typep res output-type-spec)
164 ((csubtypep type (specifier-type 'long-float))
165 (let ((res (%long-float object)))
166 (unless (typep res output-type-spec)
169 ((csubtypep type (specifier-type 'float))
170 (let ((res (%single-float object)))
171 (unless (typep res output-type-spec)
177 ((csubtypep type (specifier-type '(complex single-float)))
178 (complex (%single-float (realpart object))
179 (%single-float (imagpart object))))
180 ((csubtypep type (specifier-type '(complex double-float)))
181 (complex (%double-float (realpart object))
182 (%double-float (imagpart object))))
184 ((csubtypep type (specifier-type '(complex long-float)))
185 (complex (%long-float (realpart object))
186 (%long-float (imagpart object))))
187 ((csubtypep type (specifier-type '(complex float)))
188 (complex (%single-float (realpart object))
189 (%single-float (imagpart object))))
190 ((and (typep object 'rational)
191 (csubtypep type (specifier-type '(complex float))))
192 ;; Perhaps somewhat surprisingly, ANSI specifies
193 ;; that (COERCE FOO 'FLOAT) is a SINGLE-FLOAT,
194 ;; not dispatching on
195 ;; *READ-DEFAULT-FLOAT-FORMAT*. By analogy, we
196 ;; do the same for complex numbers. -- CSR,
198 (complex (%single-float object)))
199 ((csubtypep type (specifier-type 'complex))
203 ;; If RES has the wrong type, that means that rule of
204 ;; canonical representation for complex rationals was
205 ;; invoked. According to the Hyperspec, (coerce 7/2
206 ;; 'complex) returns 7/2. Thus, if the object was a
207 ;; rational, there is no error here.
208 (unless (or (typep res output-type-spec)
212 ((csubtypep type (specifier-type 'list))
215 ((type= type (specifier-type 'list))
216 (vector-to-list* 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 (vector-to-list* object))))
232 (t (sequence-type-too-hairy (type-specifier type))))
234 ((csubtypep type (specifier-type 'vector))
236 ;; FOO-TO-VECTOR* go through MAKE-SEQUENCE, so length
237 ;; errors are caught there. -- CSR, 2002-10-18
238 (list (list-to-vector* object output-type-spec))
239 (vector (vector-to-vector* object output-type-spec))
245 ;;; new version, which seems as though it should be better, but which
246 ;;; does not yet work
248 (defun coerce (object output-type-spec)
250 "Coerces the Object to an object of type Output-Type-Spec."
251 (flet ((coerce-error ()
252 (error 'simple-type-error
253 :format-control "~S can't be converted to type ~S."
254 :format-arguments (list object output-type-spec)))
255 (check-result (result)
256 #!+high-security (aver (typep result output-type-spec))
258 (let ((type (specifier-type output-type-spec)))
260 ((%typep object output-type-spec)
262 ((eq type *empty-type*)
264 ((csubtypep type (specifier-type 'character))
266 ((csubtypep type (specifier-type 'function))
267 (coerce-to-fun object))
271 ((csubtypep type (specifier-type 'single-float))
272 (%single-float object))
273 ((csubtypep type (specifier-type 'double-float))
274 (%double-float object))
276 ((csubtypep type (specifier-type 'long-float))
277 (%long-float object))
278 ((csubtypep type (specifier-type 'float))
279 (%single-float object))
280 ((csubtypep type (specifier-type '(complex single-float)))
281 (complex (%single-float (realpart object))
282 (%single-float (imagpart object))))
283 ((csubtypep type (specifier-type '(complex double-float)))
284 (complex (%double-float (realpart object))
285 (%double-float (imagpart object))))
287 ((csubtypep type (specifier-type '(complex long-float)))
288 (complex (%long-float (realpart object))
289 (%long-float (imagpart object))))
290 ((csubtypep type (specifier-type 'complex))
294 ;; If RES has the wrong type, that means that rule of
295 ;; canonical representation for complex rationals was
296 ;; invoked. According to the ANSI spec, (COERCE 7/2
297 ;; 'COMPLEX) returns 7/2. Thus, if the object was a
298 ;; rational, there is no error here.
299 (unless (or (typep res output-type-spec) (rationalp object))
302 ((csubtypep type (specifier-type 'list))
303 (coerce-to-list object))
304 ((csubtypep type (specifier-type 'string))
305 (check-result (coerce-to-simple-string object)))
306 ((csubtypep type (specifier-type 'bit-vector))
307 (check-result (coerce-to-bit-vector object)))
308 ((csubtypep type (specifier-type 'vector))
309 (check-result (coerce-to-vector object output-type-spec)))