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-simple-string* (make-string length) schar :list)
32 (def list-to-bit-vector* (make-array length :element-type '(mod 2))
35 (def list-to-vector* (make-sequence-of-type type length)
38 (def vector-to-vector* (make-sequence-of-type type length)
41 (def vector-to-simple-string* (make-string length) schar :vector)
43 (def vector-to-bit-vector* (make-array length :element-type '(mod 2))
46 (defun vector-to-list* (object)
47 (let ((result (list nil))
48 (length (length object)))
49 (declare (fixnum length))
50 (do ((index 0 (1+ index))
51 (splice result (cdr splice)))
52 ((= index length) (cdr result))
53 (declare (fixnum index))
54 (rplacd splice (list (aref object index))))))
56 (defun string-to-simple-string* (object)
57 (if (simple-string-p object)
59 (with-array-data ((data object)
61 (end (length object)))
62 (declare (simple-string data))
63 (subseq data start end))))
65 (defun bit-vector-to-simple-bit-vector* (object)
66 (if (simple-bit-vector-p object)
68 (with-array-data ((data object)
70 (end (length object)))
71 (declare (simple-bit-vector data))
72 (subseq data start end))))
74 (defvar *offending-datum*); FIXME: Remove after debugging COERCE.
76 ;;; These are used both by the full DEFUN function and by various
77 ;;; optimization transforms in the constant-OUTPUT-TYPE-SPEC case.
79 ;;; Most of them are INLINE so that they can be optimized when the
80 ;;; argument type is known. It might be better to do this with
81 ;;; DEFTRANSFORMs, though.
82 (declaim (inline coerce-to-list))
83 (declaim (inline coerce-to-simple-string coerce-to-bit-vector coerce-to-vector))
84 (defun coerce-to-fun (object)
85 ;; (Unlike the other COERCE-TO-FOOs, this one isn't inline, because
86 ;; it's so big and because optimizing away the outer ETYPECASE
87 ;; doesn't seem to buy us that much anyway.)
90 ;; ANSI lets us return ordinary errors (non-TYPE-ERRORs) here.
91 (cond ((macro-function object)
92 (error "~S names a macro." object))
93 ((special-operator-p object)
94 (error "~S is a special operator." object))
95 (t (fdefinition object))))
100 ((lambda instance-lambda)
101 ;; FIXME: If we go to a compiler-only implementation, this can
102 ;; become COMPILE instead of EVAL, which seems nicer to me.
103 (eval `(function ,object)))
105 (error 'simple-type-error
107 :expected-type '(or symbol
108 ;; KLUDGE: ANSI wants us to
109 ;; return a TYPE-ERROR here, and
110 ;; a TYPE-ERROR is supposed to
111 ;; describe the expected type,
112 ;; but it's not obvious how to
113 ;; describe the coerceable cons
114 ;; types, so we punt and just say
115 ;; CONS. -- WHN 20000503
117 :format-control "~S can't be coerced to a function."
118 :format-arguments (list object)))))))
119 (defun coerce-to-list (object)
121 (vector (vector-to-list* object))))
122 (defun coerce-to-simple-string (object)
124 (list (list-to-simple-string* object))
125 (string (string-to-simple-string* object))
126 (vector (vector-to-simple-string* object))))
127 (defun coerce-to-bit-vector (object)
129 (list (list-to-bit-vector* object))
130 (vector (vector-to-bit-vector* object))))
131 (defun coerce-to-simple-vector (x)
132 (if (simple-vector-p x)
134 (replace (make-array (length x)) x)))
135 (defun coerce-to-vector (object output-type-spec)
137 (list (list-to-vector* object output-type-spec))
138 (vector (vector-to-vector* object output-type-spec))))
140 ;;; old working version
141 (defun coerce (object output-type-spec)
143 "Coerce the Object to an object of type Output-Type-Spec."
144 (flet ((coerce-error ()
145 (/show0 "entering COERCE-ERROR")
146 (error 'simple-type-error
147 :format-control "~S can't be converted to type ~S."
148 :format-arguments (list object output-type-spec)))
149 (check-result (result)
150 #!+high-security (aver (typep result output-type-spec))
152 (let ((type (specifier-type output-type-spec)))
154 ((%typep object output-type-spec)
156 ((eq type *empty-type*)
158 ((csubtypep type (specifier-type 'character))
160 ((csubtypep type (specifier-type 'function))
162 (when (and (or (symbolp object)
164 (= (length object) 2)
165 (eq (car object) 'setf)))
166 (not (fboundp object)))
167 (error 'simple-type-error
169 ;; FIXME: SATISFIES FBOUNDP is a kinda bizarre broken
170 ;; type specifier, since the set of values it describes
171 ;; isn't in general constant in time. Maybe we could
172 ;; find a better way of expressing this error? (Maybe
173 ;; with the UNDEFINED-FUNCTION condition?)
174 :expected-type '(satisfies fboundp)
175 :format-control "~S isn't fbound."
176 :format-arguments (list object)))
178 (when (and (symbolp object)
179 (sb!xc:macro-function object))
180 (error 'simple-type-error
182 :expected-type '(not (satisfies sb!xc:macro-function))
183 :format-control "~S is a macro."
184 :format-arguments (list object)))
186 (when (and (symbolp object)
187 (special-operator-p object))
188 (error 'simple-type-error
190 :expected-type '(not (satisfies special-operator-p))
191 :format-control "~S is a special operator."
192 :format-arguments (list object)))
197 ((csubtypep type (specifier-type 'single-float))
198 (%single-float object))
199 ((csubtypep type (specifier-type 'double-float))
200 (%double-float object))
202 ((csubtypep type (specifier-type 'long-float))
203 (%long-float object))
204 ((csubtypep type (specifier-type 'float))
205 (%single-float object))
206 ((csubtypep type (specifier-type '(complex single-float)))
207 (complex (%single-float (realpart object))
208 (%single-float (imagpart object))))
209 ((csubtypep type (specifier-type '(complex double-float)))
210 (complex (%double-float (realpart object))
211 (%double-float (imagpart object))))
213 ((csubtypep type (specifier-type '(complex long-float)))
214 (complex (%long-float (realpart object))
215 (%long-float (imagpart object))))
216 ((csubtypep type (specifier-type 'complex))
220 ;; If RES has the wrong type, that means that rule of canonical
221 ;; representation for complex rationals was invoked. According to
222 ;; the Hyperspec, (coerce 7/2 'complex) returns 7/2. Thus, if the
223 ;; object was a rational, there is no error here.
224 (unless (or (typep res output-type-spec) (rationalp object))
227 ((csubtypep type (specifier-type 'list))
229 (vector-to-list* object)
231 ((csubtypep type (specifier-type 'string))
234 (list (list-to-simple-string* object))
235 (string (string-to-simple-string* object))
236 (vector (vector-to-simple-string* object))
239 ((csubtypep type (specifier-type 'bit-vector))
242 (list (list-to-bit-vector* object))
243 (vector (vector-to-bit-vector* object))
246 ((csubtypep type (specifier-type 'vector))
249 (list (list-to-vector* object output-type-spec))
250 (vector (vector-to-vector* object output-type-spec))
256 ;;; new version, which seems as though it should be better, but which
257 ;;; does not yet work
259 (defun coerce (object output-type-spec)
261 "Coerces the Object to an object of type Output-Type-Spec."
262 (flet ((coerce-error ()
263 (error 'simple-type-error
264 :format-control "~S can't be converted to type ~S."
265 :format-arguments (list object output-type-spec)))
266 (check-result (result)
267 #!+high-security (aver (typep result output-type-spec))
269 (let ((type (specifier-type output-type-spec)))
271 ((%typep object output-type-spec)
273 ((eq type *empty-type*)
275 ((csubtypep type (specifier-type 'character))
277 ((csubtypep type (specifier-type 'function))
278 (coerce-to-fun object))
282 ((csubtypep type (specifier-type 'single-float))
283 (%single-float object))
284 ((csubtypep type (specifier-type 'double-float))
285 (%double-float object))
287 ((csubtypep type (specifier-type 'long-float))
288 (%long-float object))
289 ((csubtypep type (specifier-type 'float))
290 (%single-float object))
291 ((csubtypep type (specifier-type '(complex single-float)))
292 (complex (%single-float (realpart object))
293 (%single-float (imagpart object))))
294 ((csubtypep type (specifier-type '(complex double-float)))
295 (complex (%double-float (realpart object))
296 (%double-float (imagpart object))))
298 ((csubtypep type (specifier-type '(complex long-float)))
299 (complex (%long-float (realpart object))
300 (%long-float (imagpart object))))
301 ((csubtypep type (specifier-type 'complex))
305 ;; If RES has the wrong type, that means that rule of
306 ;; canonical representation for complex rationals was
307 ;; invoked. According to the ANSI spec, (COERCE 7/2
308 ;; 'COMPLEX) returns 7/2. Thus, if the object was a
309 ;; rational, there is no error here.
310 (unless (or (typep res output-type-spec) (rationalp object))
313 ((csubtypep type (specifier-type 'list))
314 (coerce-to-list object))
315 ((csubtypep type (specifier-type 'string))
316 (check-result (coerce-to-simple-string object)))
317 ((csubtypep type (specifier-type 'bit-vector))
318 (check-result (coerce-to-bit-vector object)))
319 ((csubtypep type (specifier-type 'vector))
320 (check-result (coerce-to-vector object output-type-spec)))