(in-package "SB!IMPL")
-(macrolet ((def-frob (name result access src-type &optional typep)
+(macrolet ((def (name result access src-type &optional typep)
`(defun ,name (object ,@(if typep '(type) ()))
(do* ((index 0 (1+ index))
(length (length (the ,(ecase src-type
(:list '(pop in-object))
(:vector '(aref in-object index))))))))
- (def-frob list-to-simple-string* (make-string length) schar :list)
-
- (def-frob list-to-bit-vector* (make-array length :element-type '(mod 2))
- sbit :list)
-
- (def-frob list-to-vector* (make-sequence-of-type type length)
+ (def list-to-vector* (make-sequence type length)
aref :list t)
- (def-frob vector-to-vector* (make-sequence-of-type type length)
- aref :vector t)
-
- (def-frob vector-to-simple-string* (make-string length) schar :vector)
-
- (def-frob vector-to-bit-vector* (make-array length :element-type '(mod 2))
- sbit :vector))
+ (def vector-to-vector* (make-sequence type length)
+ aref :vector t))
(defun vector-to-list* (object)
(let ((result (list nil))
(declare (fixnum index))
(rplacd splice (list (aref object index))))))
-(defun string-to-simple-string* (object)
- (if (simple-string-p object)
- object
- (with-array-data ((data object)
- (start)
- (end (length object)))
- (declare (simple-string data))
- (subseq data start end))))
-
-(defun bit-vector-to-simple-bit-vector* (object)
- (if (simple-bit-vector-p object)
- object
- (with-array-data ((data object)
- (start)
- (end (length object)))
- (declare (simple-bit-vector data))
- (subseq data start end))))
-
(defvar *offending-datum*); FIXME: Remove after debugging COERCE.
;;; These are used both by the full DEFUN function and by various
;;; argument type is known. It might be better to do this with
;;; DEFTRANSFORMs, though.
(declaim (inline coerce-to-list))
-(declaim (inline coerce-to-simple-string coerce-to-bit-vector coerce-to-vector))
-(defun coerce-to-function (object)
+(declaim (inline coerce-to-vector))
+(defun coerce-to-fun (object)
;; (Unlike the other COERCE-TO-FOOs, this one isn't inline, because
;; it's so big and because optimizing away the outer ETYPECASE
;; doesn't seem to buy us that much anyway.)
cons)
:format-control "~S can't be coerced to a function."
:format-arguments (list object)))))))
+
(defun coerce-to-list (object)
(etypecase object
(vector (vector-to-list* object))))
-(defun coerce-to-simple-string (object)
- (etypecase object
- (list (list-to-simple-string* object))
- (string (string-to-simple-string* object))
- (vector (vector-to-simple-string* object))))
-(defun coerce-to-bit-vector (object)
- (etypecase object
- (list (list-to-bit-vector* object))
- (vector (vector-to-bit-vector* object))))
+
(defun coerce-to-vector (object output-type-spec)
(etypecase object
(list (list-to-vector* object output-type-spec))
;;; old working version
(defun coerce (object output-type-spec)
#!+sb-doc
- "Coerces the Object to an object of type Output-Type-Spec."
+ "Coerce the Object to an object of type Output-Type-Spec."
(flet ((coerce-error ()
(/show0 "entering COERCE-ERROR")
(error 'simple-type-error
:format-control "~S can't be converted to type ~S."
- :format-arguments (list object output-type-spec)))
- (check-result (result)
- #!+high-security
- (check-type-var result output-type-spec)
- result))
+ :format-arguments (list object output-type-spec))))
(let ((type (specifier-type output-type-spec)))
(cond
((%typep object output-type-spec)
((csubtypep type (specifier-type 'character))
(character object))
((csubtypep type (specifier-type 'function))
- #!+high-security
- (when (and (or (symbolp object)
- (and (listp object)
- (= (length object) 2)
- (eq (car object) 'setf)))
+ (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)))
- #!+high-security
(when (and (symbolp object)
(sb!xc:macro-function object))
(error 'simple-type-error
:expected-type '(not (satisfies sb!xc:macro-function))
:format-control "~S is a macro."
:format-arguments (list object)))
- #!+high-security
(when (and (symbolp object)
(special-operator-p object))
(error 'simple-type-error
:format-arguments (list object)))
(eval `#',object))
((numberp object)
- (let ((res
- (cond
- ((csubtypep type (specifier-type 'single-float))
- (%single-float object))
- ((csubtypep type (specifier-type 'double-float))
- (%double-float object))
- #!+long-float
- ((csubtypep type (specifier-type 'long-float))
- (%long-float object))
- ((csubtypep type (specifier-type 'float))
- (%single-float object))
- ((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))
- (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))
+ (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)
- (vector-to-list* 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 'string))
- (check-result
- (typecase object
- (list (list-to-simple-string* object))
- (string (string-to-simple-string* object))
- (vector (vector-to-simple-string* object))
- (t
- (coerce-error)))))
- ((csubtypep type (specifier-type 'bit-vector))
- (check-result
- (typecase object
- (list (list-to-bit-vector* object))
- (vector (vector-to-bit-vector* object))
- (t
- (coerce-error)))))
((csubtypep type (specifier-type 'vector))
- (check-result
- (typecase object
- (list (list-to-vector* object output-type-spec))
- (vector (vector-to-vector* object output-type-spec))
- (t
- (coerce-error)))))
+ (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))))))
:format-control "~S can't be converted to type ~S."
:format-arguments (list object output-type-spec)))
(check-result (result)
- #!+high-security
- (check-type-var result output-type-spec)
+ #!+high-security (aver (typep result output-type-spec))
result))
(let ((type (specifier-type output-type-spec)))
(cond
((csubtypep type (specifier-type 'character))
(character object))
((csubtypep type (specifier-type 'function))
- (coerce-to-function object))
+ (coerce-to-fun object))
((numberp object)
(let ((res
(cond