- ((%typep object output-type-spec)
- object)
- ((eq type *empty-type*)
- (coerce-error))
- ((csubtypep type (specifier-type 'character))
- (character object))
- ((csubtypep type (specifier-type 'function))
- (when (and (legal-fun-name-p object)
- (not (fboundp object)))
- (error 'simple-type-error
- :datum object
- ;; FIXME: SATISFIES FBOUNDP is a kinda bizarre broken
- ;; type specifier, since the set of values it describes
- ;; isn't in general constant in time. Maybe we could
- ;; find a better way of expressing this error? (Maybe
- ;; with the UNDEFINED-FUNCTION condition?)
- :expected-type '(satisfies fboundp)
- :format-control "~S isn't fbound."
- :format-arguments (list object)))
- (when (and (symbolp object)
- (sb!xc:macro-function object))
- (error 'simple-type-error
- :datum object
- :expected-type '(not (satisfies sb!xc:macro-function))
- :format-control "~S is a macro."
- :format-arguments (list object)))
- (when (and (symbolp object)
- (special-operator-p object))
- (error 'simple-type-error
- :datum object
- :expected-type '(not (satisfies special-operator-p))
- :format-control "~S is a special operator."
- :format-arguments (list object)))
- (eval `#',object))
- ((numberp object)
- (cond
- ((csubtypep type (specifier-type 'single-float))
- (let ((res (%single-float object)))
- (unless (typep res output-type-spec)
- (coerce-error))
- res))
- ((csubtypep type (specifier-type 'double-float))
- (let ((res (%double-float object)))
- (unless (typep res output-type-spec)
- (coerce-error))
- res))
- #!+long-float
- ((csubtypep type (specifier-type 'long-float))
- (let ((res (%long-float object)))
- (unless (typep res output-type-spec)
- (coerce-error))
- res))
- ((csubtypep type (specifier-type 'float))
- (let ((res (%single-float object)))
- (unless (typep res output-type-spec)
- (coerce-error))
- res))
- (t
- (let ((res
- (cond
- ((csubtypep type (specifier-type '(complex single-float)))
- (complex (%single-float (realpart object))
- (%single-float (imagpart object))))
- ((csubtypep type (specifier-type '(complex double-float)))
- (complex (%double-float (realpart object))
- (%double-float (imagpart object))))
- #!+long-float
- ((csubtypep type (specifier-type '(complex long-float)))
- (complex (%long-float (realpart object))
- (%long-float (imagpart object))))
- ((and (typep object 'rational)
- (csubtypep type (specifier-type '(complex float))))
- ;; Perhaps somewhat surprisingly, ANSI specifies
- ;; that (COERCE FOO 'FLOAT) is a SINGLE-FLOAT,
- ;; not dispatching on
- ;; *READ-DEFAULT-FLOAT-FORMAT*. By analogy, we
- ;; do the same for complex numbers. -- CSR,
- ;; 2002-08-06
- (complex (%single-float object)))
- ((csubtypep type (specifier-type 'complex))
- (complex object))
- (t
- (coerce-error)))))
- ;; If RES has the wrong type, that means that rule of
- ;; canonical representation for complex rationals was
- ;; invoked. According to the Hyperspec, (coerce 7/2
- ;; 'complex) returns 7/2. Thus, if the object was a
- ;; rational, there is no error here.
- (unless (or (typep res output-type-spec)
- (rationalp object))
- (coerce-error))
- res))))
- ((csubtypep type (specifier-type 'list))
- (if (vectorp object)
- (cond
- ((type= type (specifier-type 'list))
- (vector-to-list* object))
- ((type= type (specifier-type 'null))
- (if (= (length object) 0)
- 'nil
- (sequence-type-length-mismatch-error type
- (length object))))
- ((cons-type-p type)
- (multiple-value-bind (min exactp)
- (sb!kernel::cons-type-length-info type)
- (let ((length (length object)))
- (if exactp
- (unless (= length min)
- (sequence-type-length-mismatch-error type length))
- (unless (>= length min)
- (sequence-type-length-mismatch-error type length)))
- (vector-to-list* object))))
- (t (sequence-type-too-hairy (type-specifier type))))
- (coerce-error)))
- ((csubtypep type (specifier-type 'vector))
- (typecase object
- ;; FOO-TO-VECTOR* go through MAKE-SEQUENCE, so length
- ;; errors are caught there. -- CSR, 2002-10-18
- (list (list-to-vector* object output-type-spec))
- (vector (vector-to-vector* object output-type-spec))
- (t
- (coerce-error))))
- (t
- (coerce-error))))))
+ ((%typep object output-type-spec)
+ object)
+ ((eq type *empty-type*)
+ (coerce-error))
+ ((csubtypep type (specifier-type 'character))
+ (character object))
+ ((numberp object)
+ (cond
+ ((csubtypep type (specifier-type 'single-float))
+ (let ((res (%single-float object)))
+ (unless (typep res output-type-spec)
+ (coerce-error))
+ res))
+ ((csubtypep type (specifier-type 'double-float))
+ (let ((res (%double-float object)))
+ (unless (typep res output-type-spec)
+ (coerce-error))
+ res))
+ #!+long-float
+ ((csubtypep type (specifier-type 'long-float))
+ (let ((res (%long-float object)))
+ (unless (typep res output-type-spec)
+ (coerce-error))
+ res))
+ ((csubtypep type (specifier-type 'float))
+ (let ((res (%single-float object)))
+ (unless (typep res output-type-spec)
+ (coerce-error))
+ res))
+ (t
+ (let ((res
+ (cond
+ ((csubtypep type (specifier-type '(complex single-float)))
+ (complex (%single-float (realpart object))
+ (%single-float (imagpart object))))
+ ((csubtypep type (specifier-type '(complex double-float)))
+ (complex (%double-float (realpart object))
+ (%double-float (imagpart object))))
+ #!+long-float
+ ((csubtypep type (specifier-type '(complex long-float)))
+ (complex (%long-float (realpart object))
+ (%long-float (imagpart object))))
+ ((csubtypep type (specifier-type '(complex float)))
+ (complex (%single-float (realpart object))
+ (%single-float (imagpart object))))
+ ((and (typep object 'rational)
+ (csubtypep type (specifier-type '(complex float))))
+ ;; Perhaps somewhat surprisingly, ANSI specifies
+ ;; that (COERCE FOO 'FLOAT) is a SINGLE-FLOAT,
+ ;; not dispatching on
+ ;; *READ-DEFAULT-FLOAT-FORMAT*. By analogy, we
+ ;; do the same for complex numbers. -- CSR,
+ ;; 2002-08-06
+ (complex (%single-float object)))
+ ((csubtypep type (specifier-type 'complex))
+ (complex object))
+ (t
+ (coerce-error)))))
+ ;; If RES has the wrong type, that means that rule of
+ ;; canonical representation for complex rationals was
+ ;; invoked. According to the Hyperspec, (coerce 7/2
+ ;; 'complex) returns 7/2. Thus, if the object was a
+ ;; rational, there is no error here.
+ (unless (or (typep res output-type-spec)
+ (rationalp object))
+ (coerce-error))
+ res))))
+ ((csubtypep type (specifier-type 'list))
+ (if (vectorp object)
+ (cond
+ ((type= type (specifier-type 'list))
+ (vector-to-list* object))
+ ((type= type (specifier-type 'null))
+ (if (= (length object) 0)
+ 'nil
+ (sequence-type-length-mismatch-error type
+ (length object))))
+ ((cons-type-p type)
+ (multiple-value-bind (min exactp)
+ (sb!kernel::cons-type-length-info type)
+ (let ((length (length object)))
+ (if exactp
+ (unless (= length min)
+ (sequence-type-length-mismatch-error type length))
+ (unless (>= length min)
+ (sequence-type-length-mismatch-error type length)))
+ (vector-to-list* object))))
+ (t (sequence-type-too-hairy (type-specifier type))))
+ (if (sequencep object)
+ (cond
+ ((type= type (specifier-type 'list))
+ (sb!sequence:make-sequence-like
+ nil (length object) :initial-contents object))
+ ((type= type (specifier-type 'null))
+ (if (= (length object) 0)
+ 'nil
+ (sequence-type-length-mismatch-error type
+ (length object))))
+ ((cons-type-p type)
+ (multiple-value-bind (min exactp)
+ (sb!kernel::cons-type-length-info type)
+ (let ((length (length object)))
+ (if exactp
+ (unless (= length min)
+ (sequence-type-length-mismatch-error type length))
+ (unless (>= length min)
+ (sequence-type-length-mismatch-error type length)))
+ (sb!sequence:make-sequence-like
+ nil length :initial-contents object))))
+ (t (sequence-type-too-hairy (type-specifier type))))
+ (coerce-error))))
+ ((csubtypep type (specifier-type 'vector))
+ (typecase object
+ ;; FOO-TO-VECTOR* go through MAKE-SEQUENCE, so length
+ ;; errors are caught there. -- CSR, 2002-10-18
+ (list (list-to-vector* object output-type-spec))
+ (vector (vector-to-vector* object output-type-spec))
+ (sequence (sequence-to-vector* object output-type-spec))
+ (t
+ (coerce-error))))
+ ((and (csubtypep type (specifier-type 'sequence))
+ (find-class output-type-spec nil))
+ (let ((class (find-class output-type-spec)))
+ (sb!sequence:make-sequence-like
+ (sb!mop:class-prototype class)
+ (length object) :initial-contents object)))
+ ((csubtypep type (specifier-type 'function))
+ (when (and (legal-fun-name-p object)
+ (not (fboundp object)))
+ (error 'simple-type-error
+ :datum object
+ ;; FIXME: SATISFIES FBOUNDP is a kinda bizarre broken
+ ;; type specifier, since the set of values it describes
+ ;; isn't in general constant in time. Maybe we could
+ ;; find a better way of expressing this error? (Maybe
+ ;; with the UNDEFINED-FUNCTION condition?)
+ :expected-type '(satisfies fboundp)
+ :format-control "~S isn't fbound."
+ :format-arguments (list object)))
+ (when (and (symbolp object)
+ (sb!xc:macro-function object))
+ (error 'simple-type-error
+ :datum object
+ :expected-type '(not (satisfies sb!xc:macro-function))
+ :format-control "~S is a macro."
+ :format-arguments (list object)))
+ (when (and (symbolp object)
+ (special-operator-p object))
+ (error 'simple-type-error
+ :datum object
+ :expected-type '(not (satisfies special-operator-p))
+ :format-control "~S is a special operator."
+ :format-arguments (list object)))
+ (eval `#',object))
+ (t
+ (coerce-error))))))