0.7.10.20:
[sbcl/lichteblau.git] / src / code / coerce.lisp
blobab0d6676d011ae6869557986b4d40270f5232b50
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 (do* ((index 0 (1+ index))
17 (length (length (the ,(ecase src-type
18 (:list 'list)
19 (:vector 'vector))
20 object)))
21 (result ,result)
22 (in-object object))
23 ((= index length) result)
24 (declare (fixnum length index))
25 (setf (,access result index)
26 ,(ecase src-type
27 (:list '(pop in-object))
28 (:vector '(aref in-object index))))))))
30 (def list-to-vector* (make-sequence type length)
31 aref :list t)
33 (def vector-to-vector* (make-sequence type length)
34 aref :vector t))
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.
50 ;;;
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.)
60 (etypecase object
61 (symbol
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))))
68 (list
69 (case (first object)
70 ((setf)
71 (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
78 :datum object
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
88 cons)
89 :format-control "~S can't be coerced to a function."
90 :format-arguments (list object)))))))
92 (defun coerce-to-list (object)
93 (etypecase object
94 (vector (vector-to-list* object))))
96 (defun coerce-to-vector (object output-type-spec)
97 (etypecase object
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)
103 #!+sb-doc
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)))
111 (cond
112 ((%typep object output-type-spec)
113 object)
114 ((eq type *empty-type*)
115 (coerce-error))
116 ((csubtypep type (specifier-type 'character))
117 (character object))
118 ((csubtypep type (specifier-type 'function))
119 #!+high-security
120 (when (and (or (symbolp object)
121 (and (listp object)
122 (= (length object) 2)
123 (eq (car object) 'setf)))
124 (not (fboundp object)))
125 (error 'simple-type-error
126 :datum object
127 ;; FIXME: SATISFIES FBOUNDP is a kinda bizarre broken
128 ;; type specifier, since the set of values it describes
129 ;; isn't in general constant in time. Maybe we could
130 ;; find a better way of expressing this error? (Maybe
131 ;; with the UNDEFINED-FUNCTION condition?)
132 :expected-type '(satisfies fboundp)
133 :format-control "~S isn't fbound."
134 :format-arguments (list object)))
135 #!+high-security
136 (when (and (symbolp object)
137 (sb!xc:macro-function object))
138 (error 'simple-type-error
139 :datum object
140 :expected-type '(not (satisfies sb!xc:macro-function))
141 :format-control "~S is a macro."
142 :format-arguments (list object)))
143 #!+high-security
144 (when (and (symbolp object)
145 (special-operator-p object))
146 (error 'simple-type-error
147 :datum object
148 :expected-type '(not (satisfies special-operator-p))
149 :format-control "~S is a special operator."
150 :format-arguments (list object)))
151 (eval `#',object))
152 ((numberp object)
153 (cond
154 ((csubtypep type (specifier-type 'single-float))
155 (let ((res (%single-float object)))
156 (unless (typep res output-type-spec)
157 (coerce-error))
158 res))
159 ((csubtypep type (specifier-type 'double-float))
160 (let ((res (%double-float object)))
161 (unless (typep res output-type-spec)
162 (coerce-error))
163 res))
164 #!+long-float
165 ((csubtypep type (specifier-type 'long-float))
166 (let ((res (%long-float object)))
167 (unless (typep res output-type-spec)
168 (coerce-error))
169 res))
170 ((csubtypep type (specifier-type 'float))
171 (let ((res (%single-float object)))
172 (unless (typep res output-type-spec)
173 (coerce-error))
174 res))
176 (let ((res
177 (cond
178 ((csubtypep type (specifier-type '(complex single-float)))
179 (complex (%single-float (realpart object))
180 (%single-float (imagpart object))))
181 ((csubtypep type (specifier-type '(complex double-float)))
182 (complex (%double-float (realpart object))
183 (%double-float (imagpart object))))
184 #!+long-float
185 ((csubtypep type (specifier-type '(complex long-float)))
186 (complex (%long-float (realpart object))
187 (%long-float (imagpart object))))
188 ((and (typep object 'rational)
189 (csubtypep type (specifier-type '(complex float))))
190 ;; Perhaps somewhat surprisingly, ANSI specifies
191 ;; that (COERCE FOO 'FLOAT) is a SINGLE-FLOAT,
192 ;; not dispatching on
193 ;; *READ-DEFAULT-FLOAT-FORMAT*. By analogy, we
194 ;; do the same for complex numbers. -- CSR,
195 ;; 2002-08-06
196 (complex (%single-float object)))
197 ((csubtypep type (specifier-type 'complex))
198 (complex object))
200 (coerce-error)))))
201 ;; If RES has the wrong type, that means that rule of
202 ;; canonical representation for complex rationals was
203 ;; invoked. According to the Hyperspec, (coerce 7/2
204 ;; 'complex) returns 7/2. Thus, if the object was a
205 ;; rational, there is no error here.
206 (unless (or (typep res output-type-spec)
207 (rationalp object))
208 (coerce-error))
209 res))))
210 ((csubtypep type (specifier-type 'list))
211 (if (vectorp object)
212 (cond ((type= type (specifier-type 'list))
213 (vector-to-list* object))
214 ((type= type (specifier-type 'null))
215 (if (= (length object) 0)
216 'nil
217 (sequence-type-length-mismatch-error type
218 (length object))))
219 ((csubtypep (specifier-type '(cons nil t)) type)
220 (if (> (length object) 0)
221 (vector-to-list* object)
222 (sequence-type-length-mismatch-error type 0)))
223 (t (sequence-type-too-hairy (type-specifier type))))
224 (coerce-error)))
225 ((csubtypep type (specifier-type 'vector))
226 (typecase object
227 ;; FOO-TO-VECTOR* go through MAKE-SEQUENCE, so length
228 ;; errors are caught there. -- CSR, 2002-10-18
229 (list (list-to-vector* object output-type-spec))
230 (vector (vector-to-vector* object output-type-spec))
232 (coerce-error))))
234 (coerce-error))))))
236 ;;; new version, which seems as though it should be better, but which
237 ;;; does not yet work
238 #+nil
239 (defun coerce (object output-type-spec)
240 #!+sb-doc
241 "Coerces the Object to an object of type Output-Type-Spec."
242 (flet ((coerce-error ()
243 (error 'simple-type-error
244 :format-control "~S can't be converted to type ~S."
245 :format-arguments (list object output-type-spec)))
246 (check-result (result)
247 #!+high-security (aver (typep result output-type-spec))
248 result))
249 (let ((type (specifier-type output-type-spec)))
250 (cond
251 ((%typep object output-type-spec)
252 object)
253 ((eq type *empty-type*)
254 (coerce-error))
255 ((csubtypep type (specifier-type 'character))
256 (character object))
257 ((csubtypep type (specifier-type 'function))
258 (coerce-to-fun object))
259 ((numberp object)
260 (let ((res
261 (cond
262 ((csubtypep type (specifier-type 'single-float))
263 (%single-float object))
264 ((csubtypep type (specifier-type 'double-float))
265 (%double-float object))
266 #!+long-float
267 ((csubtypep type (specifier-type 'long-float))
268 (%long-float object))
269 ((csubtypep type (specifier-type 'float))
270 (%single-float object))
271 ((csubtypep type (specifier-type '(complex single-float)))
272 (complex (%single-float (realpart object))
273 (%single-float (imagpart object))))
274 ((csubtypep type (specifier-type '(complex double-float)))
275 (complex (%double-float (realpart object))
276 (%double-float (imagpart object))))
277 #!+long-float
278 ((csubtypep type (specifier-type '(complex long-float)))
279 (complex (%long-float (realpart object))
280 (%long-float (imagpart object))))
281 ((csubtypep type (specifier-type 'complex))
282 (complex object))
284 (coerce-error)))))
285 ;; If RES has the wrong type, that means that rule of
286 ;; canonical representation for complex rationals was
287 ;; invoked. According to the ANSI spec, (COERCE 7/2
288 ;; 'COMPLEX) returns 7/2. Thus, if the object was a
289 ;; rational, there is no error here.
290 (unless (or (typep res output-type-spec) (rationalp object))
291 (coerce-error))
292 res))
293 ((csubtypep type (specifier-type 'list))
294 (coerce-to-list object))
295 ((csubtypep type (specifier-type 'string))
296 (check-result (coerce-to-simple-string object)))
297 ((csubtypep type (specifier-type 'bit-vector))
298 (check-result (coerce-to-bit-vector object)))
299 ((csubtypep type (specifier-type 'vector))
300 (check-result (coerce-to-vector object output-type-spec)))
302 (coerce-error))))))