(macrolet ((def (name result access src-type &optional typep)
`(defun ,name (object ,@(if typep '(type) ()))
+ (declare (type ,(ecase src-type
+ (:list 'list)
+ (:vector 'vector)
+ (:sequence 'sequence)) object))
(do* ((index 0 (1+ index))
- (length (length (the ,(ecase src-type
- (:list 'list)
- (:vector 'vector))
- object)))
+ (length (length object))
(result ,result)
(in-object object))
- ((= index length) result)
+ ((>= index length) result)
(declare (fixnum length index))
+ (declare (type vector result))
(setf (,access result index)
,(ecase src-type
(:list '(pop in-object))
- (:vector '(aref in-object index))))))))
+ (:vector '(aref in-object index))
+ (:sequence '(elt in-object index))))))))
(def list-to-vector* (make-sequence type length)
aref :list t)
(def vector-to-vector* (make-sequence type length)
- aref :vector t))
+ aref :vector t)
+
+ (def sequence-to-vector* (make-sequence type length)
+ aref :sequence t))
(defun vector-to-list* (object)
+ (declare (type vector object))
(let ((result (list nil))
(length (length object)))
(declare (fixnum length))
(do ((index 0 (1+ index))
(splice result (cdr splice)))
- ((= index length) (cdr result))
+ ((>= index length) (cdr result))
(declare (fixnum index))
(rplacd splice (list (aref object index))))))
;; FIXME: If we go to a compiler-only implementation, this can
;; become COMPILE instead of EVAL, which seems nicer to me.
(eval `(function ,object)))
- ((instance-lambda)
- (deprecation-warning 'instance-lambda 'lambda)
- (eval `(function ,object)))
(t
(error 'simple-type-error
:datum object
object)
((eq type *empty-type*)
(coerce-error))
- ((csubtypep type (specifier-type 'character))
+ ((type= 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))
(sequence-type-length-mismatch-error type length)))
(vector-to-list* object))))
(t (sequence-type-too-hairy (type-specifier type))))
- (coerce-error)))
+ (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)))
+ (unless (sb!mop:class-finalized-p class)
+ (sb!mop:finalize-inheritance class))
+ (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))))))