;;; These functions are only needed by the interpreter, 'cause the
;;; compiler inlines them.
-(macrolet ((def-frob (name)
+(macrolet ((def (name)
`(progn
(defun ,name (array)
(,name array))
(defun (setf ,name) (value array)
(setf (,name array) value)))))
- (def-frob %array-fill-pointer)
- (def-frob %array-fill-pointer-p)
- (def-frob %array-available-elements)
- (def-frob %array-data-vector)
- (def-frob %array-displacement)
- (def-frob %array-displaced-p))
+ (def %array-fill-pointer)
+ (def %array-fill-pointer-p)
+ (def %array-available-elements)
+ (def %array-data-vector)
+ (def %array-displacement)
+ (def %array-displaced-p))
(defun %array-rank (array)
(%array-rank array))
(defun %with-array-data (array start end)
(%with-array-data-macro array start end :fail-inline? t))
+(defun %data-vector-and-index (array index)
+ (if (array-header-p array)
+ (multiple-value-bind (vector index)
+ (%with-array-data array index nil)
+ (values vector index))
+ (values array index)))
+
;;; It'd waste space to expand copies of error handling in every
;;; inline %WITH-ARRAY-DATA, so we have them call this function
;;; instead. This is just a wrapper which is known never to return.
(defun failed-%with-array-data (array start end)
(declare (notinline %with-array-data))
(%with-array-data array start end)
- (error "internal error: shouldn't be here with valid parameters"))
+ (bug "called FAILED-%WITH-ARRAY-DATA with valid array parameters?"))
\f
;;;; MAKE-ARRAY
-
(eval-when (:compile-toplevel :execute)
(sb!xc:defmacro pick-vector-type (type &rest specs)
- `(cond ,@(mapcar #'(lambda (spec)
- `(,(if (eq (car spec) t)
- t
- `(subtypep ,type ',(car spec)))
- ,@(cdr spec)))
+ `(cond ,@(mapcar (lambda (spec)
+ `(,(if (eq (car spec) t)
+ t
+ `(subtypep ,type ',(car spec)))
+ ,@(cdr spec)))
specs))))
;;; These functions are used in the implementation of MAKE-ARRAY for
;; FIXME: The data here are redundant with
;; *SPECIALIZED-ARRAY-ELEMENT-TYPE-PROPERTIES*.
(pick-vector-type type
+ (nil (values #.sb!vm:simple-array-nil-widetag 0))
(base-char (values #.sb!vm:simple-string-widetag #.sb!vm:n-byte-bits))
(bit (values #.sb!vm:simple-bit-vector-widetag 1))
((unsigned-byte 2)
(when (and displaced-index-offset (null displaced-to))
(error "can't specify :DISPLACED-INDEX-OFFSET without :DISPLACED-TO"))
(if (and simple (= array-rank 1))
- ;; Its a (simple-array * (*))
+ ;; it's a (SIMPLE-ARRAY * (*))
(multiple-value-bind (type n-bits)
(%vector-widetag-and-n-bits element-type)
(declare (type (unsigned-byte 8) type)
- (type (integer 1 256) n-bits))
+ (type (integer 0 256) n-bits))
(let* ((length (car dimensions))
(array (allocate-vector
type
(error "can't specify both :INITIAL-ELEMENT and ~
:INITIAL-CONTENTS"))
(unless (= length (length initial-contents))
- (error "There are ~D elements in the :INITIAL-CONTENTS, but ~
- the vector length is ~D."
+ (error "There are ~W elements in the :INITIAL-CONTENTS, but ~
+ the vector length is ~W."
(length initial-contents)
length))
(replace array initial-contents))
array))
- ;; It's either a complex array or a multidimensional array.
+ ;; it's either a complex array or a multidimensional array.
(let* ((total-size (reduce #'* dimensions))
(data (or displaced-to
(data-vector-from-inits
(unless (and (fixnump fill-pointer)
(>= fill-pointer 0)
(<= fill-pointer length))
- (error "invalid fill-pointer ~D"
- fill-pointer))
+ ;; FIXME: should be TYPE-ERROR?
+ (error "invalid fill-pointer ~W"
+ fill-pointer))
fill-pointer))))
(setf (%array-fill-pointer-p array) t))
(t
(setf (%array-dimension array axis) dim)
(incf axis)))
array))))
-
+
;;; DATA-VECTOR-FROM-INITS returns a simple vector that has the
;;; specified array characteristics. Dimensions is only used to pass
;;; to FILL-DATA-VECTOR for error checking on the structure of
(t
(unless (typep contents 'sequence)
(error "malformed :INITIAL-CONTENTS: ~S is not a ~
- sequence, but ~D more layer~:P needed."
+ sequence, but ~W more layer~:P needed."
contents
(- (length dimensions) axis)))
(unless (= (length contents) (car dims))
(error "malformed :INITIAL-CONTENTS: Dimension of ~
- axis ~D is ~D, but ~S is ~D long."
+ axis ~W is ~W, but ~S is ~W long."
axis (car dims) contents (length contents)))
(if (listp contents)
(dolist (content contents)
#!+long-float long-float
(complex single-float)
(complex double-float)
- #!+long-float (complex long-float))))
+ #!+long-float (complex long-float)
+ nil)))
(defun hairy-data-vector-ref (array index)
(with-array-data ((vector array) (index index) (end))
- (declare (ignore end) (optimize (safety 3)))
+ (declare (ignore end))
(etypecase vector .
#.(mapcar (lambda (type)
(let ((atype `(simple-array ,type (*))))
index))))
*specialized-array-element-types*))))
+;;; (Ordinary DATA-VECTOR-REF usage compiles into a vop, but
+;;; DATA-VECTOR-REF is also FOLDABLE, and this ordinary function
+;;; definition is needed for the compiler to use in constant folding.)
+(defun data-vector-ref (array index)
+ (hairy-data-vector-ref array index))
+
(defun hairy-data-vector-set (array index new-value)
(with-array-data ((vector array) (index index) (end))
- (declare (ignore end) (optimize (safety 3)))
+ (declare (ignore end))
(etypecase vector .
#.(mapcar (lambda (type)
(let ((atype `(simple-array ,type (*))))
(data-vector-set (the ,atype vector)
index
(the ,type
- new-value)))))
+ new-value))
+ ;; For specialized arrays, the return
+ ;; from data-vector-set would have to
+ ;; be reboxed to be a (Lisp) return
+ ;; value; instead, we use the
+ ;; already-boxed value as the return.
+ new-value)))
*specialized-array-element-types*))))
(defun %array-row-major-index (array subscripts
(list subscripts))
(let ((rank (array-rank array)))
(unless (= rank (length subscripts))
- (error "wrong number of subscripts, ~D, for array of rank ~D"
+ (error "wrong number of subscripts, ~W, for array of rank ~W"
(length subscripts) rank))
(if (array-header-p array)
(do ((subs (nreverse subscripts) (cdr subs))
(declare (list subs) (fixnum axis chunk-size result))
(let ((index (car subs))
(dim (%array-dimension array axis)))
- (declare (fixnum index dim))
- (unless (< -1 index dim)
+ (declare (fixnum dim))
+ (unless (and (fixnump index) (< -1 index dim))
(if invalid-index-error-p
- (error "invalid index ~D~[~;~:; on axis ~:*~D~] in ~S"
- index axis array)
+ (error 'simple-type-error
+ :format-control "invalid index ~W~[~;~:; on axis ~:*~W~] in ~S"
+ :format-arguments (list index axis array)
+ :datum index
+ :expected-type `(integer 0 (,dim)))
(return-from %array-row-major-index nil)))
- (incf result (* chunk-size index))
+ (incf result (* chunk-size (the fixnum index)))
(setf chunk-size (* chunk-size dim))))
- (let ((index (first subscripts)))
- (unless (< -1 index (length (the (simple-array * (*)) array)))
+ (let ((index (first subscripts))
+ (length (length (the (simple-array * (*)) array))))
+ (unless (and (fixnump index) (< -1 index length))
(if invalid-index-error-p
- (error "invalid index ~D in ~S" index array)
+ ;; FIXME: perhaps this should share a format-string
+ ;; with INVALID-ARRAY-INDEX-ERROR or
+ ;; INDEX-TOO-LARGE-ERROR?
+ (error 'simple-type-error
+ :format-control "invalid index ~W in ~S"
+ :format-arguments (list index array)
+ :datum index
+ :expected-type `(integer 0 (,length)))
(return-from %array-row-major-index nil)))
index))))
(defun array-in-bounds-p (array &rest subscripts)
#!+sb-doc
- "Return T if the Subscipts are in bounds for the Array, Nil otherwise."
+ "Return T if the SUBSCIPTS are in bounds for the ARRAY, NIL otherwise."
(if (%array-row-major-index array subscripts nil)
t))
(defun aref (array &rest subscripts)
#!+sb-doc
- "Return the element of the Array specified by the Subscripts."
+ "Return the element of the ARRAY specified by the SUBSCRIPTS."
(row-major-aref array (%array-row-major-index array subscripts)))
(defun %aset (array &rest stuff)
;;; ZOO
;;; But that doesn't seem to be what happens in CMU CL.
;;;
+;;; KLUDGE: this is probably because ANSI, in its wisdom (CLHS
+;;; 5.1.2.5) requires implementations to support
+;;; (SETF (APPLY #'AREF ...) ...)
+;;; [and also #'BIT and #'SBIT]. Yes, this is terrifying, and it's
+;;; also terrifying that this sequence of definitions causes it to
+;;; work.
+;;;
;;; Also, it would be nice to make DESCRIBE FOO tell whether a symbol
;;; has a setf expansion and/or a setf function defined.
"Return the type of the elements of the array"
(let ((widetag (widetag-of array)))
(macrolet ((pick-element-type (&rest stuff)
- `(cond ,@(mapcar #'(lambda (stuff)
- (cons
- (let ((item (car stuff)))
- (cond ((eq item t)
- t)
- ((listp item)
- (cons 'or
- (mapcar (lambda (x)
- `(= widetag ,x))
- item)))
- (t
- `(= widetag ,item))))
- (cdr stuff)))
- stuff))))
+ `(cond ,@(mapcar (lambda (stuff)
+ (cons
+ (let ((item (car stuff)))
+ (cond ((eq item t)
+ t)
+ ((listp item)
+ (cons 'or
+ (mapcar (lambda (x)
+ `(= widetag ,x))
+ item)))
+ (t
+ `(= widetag ,item))))
+ (cdr stuff)))
+ stuff))))
;; FIXME: The data here are redundant with
;; *SPECIALIZED-ARRAY-ELEMENT-TYPE-PROPERTIES*.
(pick-element-type
+ (sb!vm:simple-array-nil-widetag nil)
((sb!vm:simple-string-widetag sb!vm:complex-string-widetag) 'base-char)
((sb!vm:simple-bit-vector-widetag
sb!vm:complex-bit-vector-widetag) 'bit)
(declare (ignore start end))
(array-element-type array)))
(t
- (error "~S is not an array." array))))))
+ (error 'type-error :datum array :expected-type 'array))))))
(defun array-rank (array)
#!+sb-doc
(error "Vector axis is not zero: ~S" axis-number))
(length (the (simple-array * (*)) array)))
((>= axis-number (%array-rank array))
- (error "~D is too big; ~S only has ~D dimension~:P."
+ (error "Axis number ~W is too big; ~S only has ~D dimension~:P."
axis-number array (%array-rank array)))
(t
(%array-dimension array axis-number))))
(unless (array-header-p vector)
(macrolet ((frob (name &rest things)
`(etypecase ,name
+ ((simple-array nil (*)) (error 'cell-error
+ :name 'nil-array-element))
,@(mapcar (lambda (thing)
(destructuring-bind (type-spec fill-value)
thing
(defun zap-array-data-aux (old-data old-dims offset new-data new-dims)
(declare (fixnum offset))
- (let ((limits (mapcar #'(lambda (x y)
- (declare (fixnum x y))
- (1- (the fixnum (min x y))))
+ (let ((limits (mapcar (lambda (x y)
+ (declare (fixnum x y))
+ (1- (the fixnum (min x y))))
old-dims new-dims)))
(macrolet ((bump-index-list (index limits)
`(do ((subscripts ,index (cdr subscripts))