928f24ba7c0f1e60fb41e74bcc341886ffb91c50
[sbcl.git] / src / code / coerce.lisp
1 ;;;; COERCE and related code
2
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.
11
12 (in-package "SB!IMPL")
13
14 (macrolet ((def (name result access src-type &optional typep)
15              `(defun ,name (object ,@(if typep '(type) ()))
16                 (declare (type ,(ecase src-type
17                                        (:list 'list)
18                                        (:vector 'vector)
19                                        (:sequence 'sequence)) object))
20                 (do* ((index 0 (1+ index))
21                       (length (length object))
22                       (result ,result)
23                       (in-object object))
24                      ((>= index length) result)
25                   (declare (fixnum length index))
26                   (declare (type vector result))
27                   (setf (,access result index)
28                         ,(ecase src-type
29                            (:list '(pop in-object))
30                            (:vector '(aref in-object index))
31                            (:sequence '(elt in-object index))))))))
32
33   (def list-to-vector* (make-sequence type length)
34     aref :list t)
35
36   (def vector-to-vector* (make-sequence type length)
37     aref :vector t)
38
39   (def sequence-to-vector* (make-sequence type length)
40     aref :sequence t))
41
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))))))
52
53 (defvar *offending-datum*); FIXME: Remove after debugging COERCE.
54
55 ;;; These are used both by the full DEFUN function and by various
56 ;;; optimization transforms in the constant-OUTPUT-TYPE-SPEC case.
57 ;;;
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.)
67   (etypecase object
68     (symbol
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))))
75     (list
76      (case (first object)
77        ((setf)
78         (fdefinition object))
79        ((lambda)
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)))
83        ((instance-lambda)
84         (deprecation-error "0.9.3.32" 'instance-lambda 'lambda))
85        (t
86         (error 'simple-type-error
87                :datum object
88                :expected-type '(or symbol
89                                    ;; KLUDGE: ANSI wants us to
90                                    ;; return a TYPE-ERROR here, and
91                                    ;; a TYPE-ERROR is supposed to
92                                    ;; describe the expected type,
93                                    ;; but it's not obvious how to
94                                    ;; describe the coerceable cons
95                                    ;; types, so we punt and just say
96                                    ;; CONS. -- WHN 20000503
97                                    cons)
98                :format-control "~S can't be coerced to a function."
99                :format-arguments (list object)))))))
100
101 (defun coerce-to-list (object)
102   (etypecase object
103     (vector (vector-to-list* object))))
104
105 (defun coerce-to-vector (object output-type-spec)
106   (etypecase object
107     (list (list-to-vector* object output-type-spec))
108     (vector (vector-to-vector* object output-type-spec))))
109
110 ;;; old working version
111 (defun coerce (object output-type-spec)
112   #!+sb-doc
113   "Coerce the Object to an object of type Output-Type-Spec."
114   (flet ((coerce-error ()
115            (/show0 "entering COERCE-ERROR")
116            (error 'simple-type-error
117                   :format-control "~S can't be converted to type ~S."
118                   :format-arguments (list object output-type-spec)
119                   :datum object
120                   :expected-type output-type-spec)))
121     (let ((type (specifier-type output-type-spec)))
122       (cond
123         ((%typep object output-type-spec)
124          object)
125         ((eq type *empty-type*)
126          (coerce-error))
127         ((csubtypep type (specifier-type 'character))
128          (character object))
129         ((numberp object)
130          (cond
131            ((csubtypep type (specifier-type 'single-float))
132             (let ((res (%single-float object)))
133               (unless (typep res output-type-spec)
134                 (coerce-error))
135               res))
136            ((csubtypep type (specifier-type 'double-float))
137             (let ((res (%double-float object)))
138               (unless (typep res output-type-spec)
139                 (coerce-error))
140               res))
141            #!+long-float
142            ((csubtypep type (specifier-type 'long-float))
143             (let ((res (%long-float object)))
144               (unless (typep res output-type-spec)
145                 (coerce-error))
146               res))
147            ((csubtypep type (specifier-type 'float))
148             (let ((res (%single-float object)))
149               (unless (typep res output-type-spec)
150                 (coerce-error))
151               res))
152            (t
153             (let ((res
154                    (cond
155                      ((csubtypep type (specifier-type '(complex single-float)))
156                       (complex (%single-float (realpart object))
157                                (%single-float (imagpart object))))
158                      ((csubtypep type (specifier-type '(complex double-float)))
159                       (complex (%double-float (realpart object))
160                                (%double-float (imagpart object))))
161                      #!+long-float
162                      ((csubtypep type (specifier-type '(complex long-float)))
163                       (complex (%long-float (realpart object))
164                                (%long-float (imagpart object))))
165                      ((csubtypep type (specifier-type '(complex float)))
166                       (complex (%single-float (realpart object))
167                                (%single-float (imagpart object))))
168                      ((and (typep object 'rational)
169                            (csubtypep type (specifier-type '(complex float))))
170                       ;; Perhaps somewhat surprisingly, ANSI specifies
171                       ;; that (COERCE FOO 'FLOAT) is a SINGLE-FLOAT,
172                       ;; not dispatching on
173                       ;; *READ-DEFAULT-FLOAT-FORMAT*.  By analogy, we
174                       ;; do the same for complex numbers. -- CSR,
175                       ;; 2002-08-06
176                       (complex (%single-float object)))
177                      ((csubtypep type (specifier-type 'complex))
178                       (complex object))
179                      (t
180                       (coerce-error)))))
181               ;; If RES has the wrong type, that means that rule of
182               ;; canonical representation for complex rationals was
183               ;; invoked. According to the Hyperspec, (coerce 7/2
184               ;; 'complex) returns 7/2. Thus, if the object was a
185               ;; rational, there is no error here.
186               (unless (or (typep res output-type-spec)
187                           (rationalp object))
188                 (coerce-error))
189               res))))
190         ((csubtypep type (specifier-type 'list))
191          (if (vectorp object)
192              (cond
193                ((type= type (specifier-type 'list))
194                 (vector-to-list* object))
195                ((type= type (specifier-type 'null))
196                 (if (= (length object) 0)
197                     'nil
198                     (sequence-type-length-mismatch-error type
199                                                          (length object))))
200                ((cons-type-p type)
201                 (multiple-value-bind (min exactp)
202                     (sb!kernel::cons-type-length-info type)
203                   (let ((length (length object)))
204                     (if exactp
205                         (unless (= length min)
206                           (sequence-type-length-mismatch-error type length))
207                         (unless (>= length min)
208                           (sequence-type-length-mismatch-error type length)))
209                     (vector-to-list* object))))
210                (t (sequence-type-too-hairy (type-specifier type))))
211              (if (sequencep object)
212                  (cond
213                    ((type= type (specifier-type 'list))
214                     (sb!sequence:make-sequence-like
215                      nil (length object) :initial-contents object))
216                    ((type= type (specifier-type 'null))
217                     (if (= (length object) 0)
218                         'nil
219                         (sequence-type-length-mismatch-error type
220                                                              (length object))))
221                    ((cons-type-p type)
222                     (multiple-value-bind (min exactp)
223                         (sb!kernel::cons-type-length-info type)
224                       (let ((length (length object)))
225                         (if exactp
226                             (unless (= length min)
227                               (sequence-type-length-mismatch-error type length))
228                             (unless (>= length min)
229                               (sequence-type-length-mismatch-error type length)))
230                         (sb!sequence:make-sequence-like
231                          nil length :initial-contents object))))
232                    (t (sequence-type-too-hairy (type-specifier type))))
233                  (coerce-error))))
234         ((csubtypep type (specifier-type 'vector))
235          (typecase object
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))
240            (sequence (sequence-to-vector* object output-type-spec))
241            (t
242             (coerce-error))))
243         ((and (csubtypep type (specifier-type 'sequence))
244               (find-class output-type-spec nil))
245          (let ((class (find-class output-type-spec)))
246            (sb!sequence:make-sequence-like
247             (sb!mop:class-prototype class)
248             (length object) :initial-contents object)))
249         ((csubtypep type (specifier-type 'function))
250          (when (and (legal-fun-name-p object)
251                     (not (fboundp object)))
252            (error 'simple-type-error
253                   :datum object
254                   ;; FIXME: SATISFIES FBOUNDP is a kinda bizarre broken
255                   ;; type specifier, since the set of values it describes
256                   ;; isn't in general constant in time. Maybe we could
257                   ;; find a better way of expressing this error? (Maybe
258                   ;; with the UNDEFINED-FUNCTION condition?)
259                   :expected-type '(satisfies fboundp)
260                :format-control "~S isn't fbound."
261                :format-arguments (list object)))
262          (when (and (symbolp object)
263                     (sb!xc:macro-function object))
264            (error 'simple-type-error
265                   :datum object
266                   :expected-type '(not (satisfies sb!xc:macro-function))
267                   :format-control "~S is a macro."
268                   :format-arguments (list object)))
269          (when (and (symbolp object)
270                     (special-operator-p object))
271            (error 'simple-type-error
272                   :datum object
273                   :expected-type '(not (satisfies special-operator-p))
274                   :format-control "~S is a special operator."
275                   :format-arguments (list object)))
276          (eval `#',object))
277         (t
278          (coerce-error))))))
279
280 ;;; new version, which seems as though it should be better, but which
281 ;;; does not yet work
282 #+nil
283 (defun coerce (object output-type-spec)
284   #!+sb-doc
285   "Coerces the Object to an object of type Output-Type-Spec."
286   (flet ((coerce-error ()
287            (error 'simple-type-error
288                   :format-control "~S can't be converted to type ~S."
289                   :format-arguments (list object output-type-spec)))
290          (check-result (result)
291            #!+high-security (aver (typep result output-type-spec))
292            result))
293     (let ((type (specifier-type output-type-spec)))
294       (cond
295         ((%typep object output-type-spec)
296          object)
297         ((eq type *empty-type*)
298          (coerce-error))
299         ((csubtypep type (specifier-type 'character))
300          (character object))
301         ((csubtypep type (specifier-type 'function))
302          (coerce-to-fun object))
303         ((numberp object)
304          (let ((res
305                 (cond
306                   ((csubtypep type (specifier-type 'single-float))
307                    (%single-float object))
308                   ((csubtypep type (specifier-type 'double-float))
309                    (%double-float object))
310                   #!+long-float
311                   ((csubtypep type (specifier-type 'long-float))
312                    (%long-float object))
313                   ((csubtypep type (specifier-type 'float))
314                    (%single-float object))
315                   ((csubtypep type (specifier-type '(complex single-float)))
316                    (complex (%single-float (realpart object))
317                             (%single-float (imagpart object))))
318                   ((csubtypep type (specifier-type '(complex double-float)))
319                    (complex (%double-float (realpart object))
320                             (%double-float (imagpart object))))
321                   #!+long-float
322                   ((csubtypep type (specifier-type '(complex long-float)))
323                    (complex (%long-float (realpart object))
324                             (%long-float (imagpart object))))
325                   ((csubtypep type (specifier-type 'complex))
326                    (complex object))
327                   (t
328                    (coerce-error)))))
329            ;; If RES has the wrong type, that means that rule of
330            ;; canonical representation for complex rationals was
331            ;; invoked. According to the ANSI spec, (COERCE 7/2
332            ;; 'COMPLEX) returns 7/2. Thus, if the object was a
333            ;; rational, there is no error here.
334            (unless (or (typep res output-type-spec) (rationalp object))
335              (coerce-error))
336            res))
337         ((csubtypep type (specifier-type 'list))
338          (coerce-to-list object))
339         ((csubtypep type (specifier-type 'string))
340          (check-result (coerce-to-simple-string object)))
341         ((csubtypep type (specifier-type 'bit-vector))
342          (check-result (coerce-to-bit-vector object)))
343         ((csubtypep type (specifier-type 'vector))
344          (check-result (coerce-to-vector object output-type-spec)))
345         (t
346          (coerce-error))))))