X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcode%2Farray.lisp;h=9d1045d3a44260d39b9d0f80aa03351e294a9ee8;hb=2db3b6b4cb740d5b6512459c223859f747807b09;hp=9b6e9fb13ae0b2d4a2dfcbb132d316ae789a5949;hpb=aa2dc9529460ea0d9c99998dc87283fc1a43e808;p=sbcl.git diff --git a/src/code/array.lisp b/src/code/array.lisp index 9b6e9fb..9d1045d 100644 --- a/src/code/array.lisp +++ b/src/code/array.lisp @@ -17,20 +17,20 @@ ;;;; miscellaneous accessor functions -;;; These functions are needed by the interpreter, 'cause the compiler -;;; inlines them. -(macrolet ((def-frob (name) +;;; These functions are only needed by the interpreter, 'cause the +;;; compiler inlines them. +(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)) @@ -46,52 +46,39 @@ (fixnum index)) (%check-bound array bound index)) -;;; the guts of the WITH-ARRAY-DATA macro (except when DEFTRANSFORM -;;; %WITH-ARRAY-DATA takes over) (defun %with-array-data (array start end) - (declare (array array) (type index start) (type (or index null) end)) - ;; FIXME: The VALUES declaration here is correct, but as of SBCL - ;; 0.6.6, the corresponding runtime assertion is implemented - ;; horribly inefficiently, with a full call to %TYPEP for every - ;; call to this function. As a quick fix, I commented it out, - ;; but the proper fix would be to fix up type checking. - ;; - ;; A simpler test case for the optimization bug is - ;; (DEFUN FOO (X) - ;; (DECLARE (TYPE INDEXOID X)) - ;; (THE (VALUES INDEXOID) - ;; (VALUES X))) - ;; which also compiles to a full call to %TYPEP. - #+nil (declare (values (simple-array * (*)) index index index)) - (let* ((size (array-total-size array)) - (end (cond (end - (unless (<= end size) - (error "End ~D is greater than total size ~D." - end size)) - end) - (t size)))) - (when (> start end) - (error "Start ~D is greater than end ~D." start end)) - (do ((data array (%array-data-vector data)) - (cumulative-offset 0 - (+ cumulative-offset - (%array-displacement data)))) - ((not (array-header-p data)) - (values (the (simple-array * (*)) data) - (the index (+ cumulative-offset start)) - (the index (+ cumulative-offset end)) - (the index cumulative-offset))) - (declare (type index cumulative-offset))))) + (%with-array-data-macro array start end :fail-inline? t)) + +(defun %data-vector-and-index (array index) + (if (array-header-p array) + (%with-array-data array index nil) + (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) + (bug "called FAILED-%WITH-ARRAY-DATA with valid array parameters?")) ;;;; MAKE-ARRAY - +(defun upgraded-array-element-type (spec &optional environment) + #!+sb-doc + "Return the element type that will actually be used to implement an array + with the specifier :ELEMENT-TYPE Spec." + (declare (ignore environment)) + (if (unknown-type-p (specifier-type spec)) + (error "undefined type: ~S" spec) + (type-specifier (array-type-specialized-element-type + (specifier-type `(array ,spec)))))) (eval-when (:compile-toplevel :execute) - (sb!xc:defmacro pick-type (type &rest specs) - `(cond ,@(mapcar #'(lambda (spec) - `(,(if (eq (car spec) t) + (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))) + ,@(cdr spec))) specs)))) ;;; These functions are used in the implementation of MAKE-ARRAY for @@ -101,7 +88,7 @@ ;;; MAKE-ARRAY for any non-simple array. Thus, there's some value to ;;; making this somewhat efficient, at least not doing full calls to ;;; SUBTYPEP in the easy cases. -(defun %vector-type-code (type) +(defun %vector-widetag-and-n-bits (type) (case type ;; Pick off some easy common cases. ;; @@ -110,64 +97,68 @@ ;; on smarter compiler transforms which do the calculation once ;; and for all in any reasonable user programs.) ((t) - (values #.sb!vm:simple-vector-type #.sb!vm:word-bits)) - ((character base-char) - (values #.sb!vm:simple-string-type #.sb!vm:byte-bits)) + (values #.sb!vm:simple-vector-widetag #.sb!vm:n-word-bits)) + ((character base-char standard-char) + (values #.sb!vm:simple-string-widetag #.sb!vm:n-byte-bits)) ((bit) - (values #.sb!vm:simple-bit-vector-type 1)) + (values #.sb!vm:simple-bit-vector-widetag 1)) ;; OK, we have to wade into SUBTYPEPing after all. (t - (pick-type type - (base-char (values #.sb!vm:simple-string-type #.sb!vm:byte-bits)) - (bit (values #.sb!vm:simple-bit-vector-type 1)) + ;; 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) - (values #.sb!vm:simple-array-unsigned-byte-2-type 2)) + (values #.sb!vm:simple-array-unsigned-byte-2-widetag 2)) ((unsigned-byte 4) - (values #.sb!vm:simple-array-unsigned-byte-4-type 4)) + (values #.sb!vm:simple-array-unsigned-byte-4-widetag 4)) ((unsigned-byte 8) - (values #.sb!vm:simple-array-unsigned-byte-8-type 8)) + (values #.sb!vm:simple-array-unsigned-byte-8-widetag 8)) ((unsigned-byte 16) - (values #.sb!vm:simple-array-unsigned-byte-16-type 16)) + (values #.sb!vm:simple-array-unsigned-byte-16-widetag 16)) ((unsigned-byte 32) - (values #.sb!vm:simple-array-unsigned-byte-32-type 32)) + (values #.sb!vm:simple-array-unsigned-byte-32-widetag 32)) ((signed-byte 8) - (values #.sb!vm:simple-array-signed-byte-8-type 8)) + (values #.sb!vm:simple-array-signed-byte-8-widetag 8)) ((signed-byte 16) - (values #.sb!vm:simple-array-signed-byte-16-type 16)) + (values #.sb!vm:simple-array-signed-byte-16-widetag 16)) ((signed-byte 30) - (values #.sb!vm:simple-array-signed-byte-30-type 32)) + (values #.sb!vm:simple-array-signed-byte-30-widetag 32)) ((signed-byte 32) - (values #.sb!vm:simple-array-signed-byte-32-type 32)) - (single-float (values #.sb!vm:simple-array-single-float-type 32)) - (double-float (values #.sb!vm:simple-array-double-float-type 64)) + (values #.sb!vm:simple-array-signed-byte-32-widetag 32)) + (single-float (values #.sb!vm:simple-array-single-float-widetag 32)) + (double-float (values #.sb!vm:simple-array-double-float-widetag 64)) #!+long-float (long-float - (values #.sb!vm:simple-array-long-float-type #!+x86 96 #!+sparc 128)) + (values #.sb!vm:simple-array-long-float-widetag + #!+x86 96 #!+sparc 128)) ((complex single-float) - (values #.sb!vm:simple-array-complex-single-float-type 64)) + (values #.sb!vm:simple-array-complex-single-float-widetag 64)) ((complex double-float) - (values #.sb!vm:simple-array-complex-double-float-type 128)) + (values #.sb!vm:simple-array-complex-double-float-widetag 128)) #!+long-float ((complex long-float) - (values #.sb!vm:simple-array-complex-long-float-type + (values #.sb!vm:simple-array-complex-long-float-widetag #!+x86 192 #!+sparc 256)) - (t (values #.sb!vm:simple-vector-type #.sb!vm:word-bits)))))) -(defun %complex-vector-type-code (type) + (t (values #.sb!vm:simple-vector-widetag #.sb!vm:n-word-bits)))))) +(defun %complex-vector-widetag (type) (case type ;; Pick off some easy common cases. ((t) - #.sb!vm:complex-vector-type) + #.sb!vm:complex-vector-widetag) ((character base-char) - #.sb!vm:complex-string-type) + #.sb!vm:complex-string-widetag) ((bit) - #.sb!vm:complex-bit-vector-type) + #.sb!vm:complex-bit-vector-widetag) ;; OK, we have to wade into SUBTYPEPing after all. (t - (pick-type type - (base-char #.sb!vm:complex-string-type) - (bit #.sb!vm:complex-bit-vector-type) - (t #.sb!vm:complex-vector-type))))) + (pick-vector-type type + (base-char #.sb!vm:complex-string-widetag) + (bit #.sb!vm:complex-bit-vector-widetag) + (t #.sb!vm:complex-vector-widetag))))) (defun make-array (dimensions &key (element-type t) @@ -183,19 +174,20 @@ (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 * (*)) - (multiple-value-bind (type bits) (%vector-type-code element-type) + ;; 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) bits)) + (type (integer 0 256) n-bits)) (let* ((length (car dimensions)) (array (allocate-vector type length - (ceiling (* (if (= type sb!vm:simple-string-type) + (ceiling (* (if (= type sb!vm:simple-string-widetag) (1+ length) length) - bits) - sb!vm:word-bits)))) + n-bits) + sb!vm:n-word-bits)))) (declare (type index length)) (when initial-element-p (fill array initial-element)) @@ -204,13 +196,13 @@ (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 @@ -218,9 +210,9 @@ initial-contents initial-element initial-element-p))) (array (make-array-header (cond ((= array-rank 1) - (%complex-vector-type-code element-type)) - (simple sb!vm:simple-array-type) - (t sb!vm:complex-array-type)) + (%complex-vector-widetag element-type)) + (simple sb!vm:simple-array-widetag) + (t sb!vm:complex-array-widetag)) array-rank))) (cond (fill-pointer (unless (= array-rank 1) @@ -234,8 +226,9 @@ (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 @@ -296,12 +289,12 @@ (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) @@ -336,11 +329,12 @@ #!+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 (*)))) @@ -349,9 +343,15 @@ 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 (*)))) @@ -359,7 +359,13 @@ (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 @@ -368,7 +374,7 @@ (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)) @@ -379,24 +385,35 @@ (declare (list subs) (fixnum axis chunk-size result)) (let ((index (car subs)) (dim (%array-dimension array axis))) - (declare (fixnum index dim)) + (declare (fixnum dim)) (unless (< -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 (< -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 - "Returns 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)) @@ -405,7 +422,7 @@ (defun aref (array &rest subscripts) #!+sb-doc - "Returns 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) @@ -429,6 +446,13 @@ ;;; 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. @@ -440,7 +464,7 @@ (defun row-major-aref (array index) #!+sb-doc - "Returns the element of array corressponding to the row-major index. This is + "Return the element of array corressponding to the row-major index. This is SETF'able." (declare (optimize (safety 1))) (row-major-aref array index)) @@ -451,7 +475,7 @@ (defun svref (simple-vector index) #!+sb-doc - "Returns the Index'th element of the given Simple-Vector." + "Return the INDEX'th element of the given Simple-Vector." (declare (optimize (safety 1))) (aref simple-vector index)) @@ -461,7 +485,7 @@ (defun bit (bit-array &rest subscripts) #!+sb-doc - "Returns the bit from the Bit-Array at the specified Subscripts." + "Return the bit from the BIT-ARRAY at the specified SUBSCRIPTS." (declare (type (array bit) bit-array) (optimize (safety 1))) (row-major-aref bit-array (%array-row-major-index bit-array subscripts))) @@ -482,7 +506,7 @@ (defun sbit (simple-bit-array &rest subscripts) #!+sb-doc - "Returns the bit from the Simple-Bit-Array at the specified Subscripts." + "Return the bit from SIMPLE-BIT-ARRAY at the specified SUBSCRIPTS." (declare (type (simple-array bit) simple-bit-array) (optimize (safety 1))) (row-major-aref simple-bit-array (%array-row-major-index simple-bit-array subscripts))) @@ -510,76 +534,83 @@ (defun array-element-type (array) #!+sb-doc - "Returns the type of the elements of the array" - (let ((type (get-type array))) + "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) - `(= type ,x)) - item))) - (t - `(= type ,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-string-type sb!vm:complex-string-type) 'base-char) - ((sb!vm:simple-bit-vector-type sb!vm:complex-bit-vector-type) 'bit) - (sb!vm:simple-vector-type t) - (sb!vm:simple-array-unsigned-byte-2-type '(unsigned-byte 2)) - (sb!vm:simple-array-unsigned-byte-4-type '(unsigned-byte 4)) - (sb!vm:simple-array-unsigned-byte-8-type '(unsigned-byte 8)) - (sb!vm:simple-array-unsigned-byte-16-type '(unsigned-byte 16)) - (sb!vm:simple-array-unsigned-byte-32-type '(unsigned-byte 32)) - (sb!vm:simple-array-signed-byte-8-type '(signed-byte 8)) - (sb!vm:simple-array-signed-byte-16-type '(signed-byte 16)) - (sb!vm:simple-array-signed-byte-30-type '(signed-byte 30)) - (sb!vm:simple-array-signed-byte-32-type '(signed-byte 32)) - (sb!vm:simple-array-single-float-type 'single-float) - (sb!vm:simple-array-double-float-type 'double-float) + (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) + (sb!vm:simple-vector-widetag t) + (sb!vm:simple-array-unsigned-byte-2-widetag '(unsigned-byte 2)) + (sb!vm:simple-array-unsigned-byte-4-widetag '(unsigned-byte 4)) + (sb!vm:simple-array-unsigned-byte-8-widetag '(unsigned-byte 8)) + (sb!vm:simple-array-unsigned-byte-16-widetag '(unsigned-byte 16)) + (sb!vm:simple-array-unsigned-byte-32-widetag '(unsigned-byte 32)) + (sb!vm:simple-array-signed-byte-8-widetag '(signed-byte 8)) + (sb!vm:simple-array-signed-byte-16-widetag '(signed-byte 16)) + (sb!vm:simple-array-signed-byte-30-widetag '(signed-byte 30)) + (sb!vm:simple-array-signed-byte-32-widetag '(signed-byte 32)) + (sb!vm:simple-array-single-float-widetag 'single-float) + (sb!vm:simple-array-double-float-widetag 'double-float) #!+long-float - (sb!vm:simple-array-long-float-type 'long-float) - (sb!vm:simple-array-complex-single-float-type '(complex single-float)) - (sb!vm:simple-array-complex-double-float-type '(complex double-float)) + (sb!vm:simple-array-long-float-widetag 'long-float) + (sb!vm:simple-array-complex-single-float-widetag + '(complex single-float)) + (sb!vm:simple-array-complex-double-float-widetag + '(complex double-float)) #!+long-float - (sb!vm:simple-array-complex-long-float-type '(complex long-float)) - ((sb!vm:simple-array-type sb!vm:complex-vector-type - sb!vm:complex-array-type) + (sb!vm:simple-array-complex-long-float-widetag '(complex long-float)) + ((sb!vm:simple-array-widetag + sb!vm:complex-vector-widetag + sb!vm:complex-array-widetag) (with-array-data ((array array) (start) (end)) (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 - "Returns the number of dimensions of the Array." + "Return the number of dimensions of ARRAY." (if (array-header-p array) (%array-rank array) 1)) (defun array-dimension (array axis-number) #!+sb-doc - "Returns length of dimension Axis-Number of the Array." + "Return the length of dimension AXIS-NUMBER of ARRAY." (declare (array array) (type index axis-number)) (cond ((not (array-header-p array)) (unless (= axis-number 0) (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)))) (defun array-dimensions (array) #!+sb-doc - "Returns a list whose elements are the dimensions of the array" + "Return a list whose elements are the dimensions of the array" (declare (array array)) (if (array-header-p array) (do ((results nil (cons (array-dimension array index) results)) @@ -589,7 +620,7 @@ (defun array-total-size (array) #!+sb-doc - "Returns the total number of elements in the Array." + "Return the total number of elements in the Array." (declare (array array)) (if (array-header-p array) (%array-available-elements array) @@ -597,14 +628,17 @@ (defun array-displacement (array) #!+sb-doc - "Returns values of :displaced-to and :displaced-index-offset options to - make-array, or the defaults nil and 0 if not a displaced array." - (declare (array array)) - (values (%array-data-vector array) (%array-displacement array))) + "Return the values of :DISPLACED-TO and :DISPLACED-INDEX-offset + options to MAKE-ARRAY, or NIL and 0 if not a displaced array." + (declare (type array array)) + (if (and (array-header-p array) ; if unsimple and + (%array-displaced-p array)) ; displaced + (values (%array-data-vector array) (%array-displacement array)) + (values nil 0))) (defun adjustable-array-p (array) #!+sb-doc - "Returns T if (adjust-array array...) would return an array identical + "Return T if (ADJUST-ARRAY ARRAY...) would return an array identical to the argument, this happens for complex arrays." (declare (array array)) (not (typep array 'simple-array))) @@ -643,6 +677,11 @@ :format-control "~S is not an array with a fill pointer." :format-arguments (list vector)))) +;;; FIXME: It'd probably make sense to use a MACROLET to share the +;;; guts of VECTOR-PUSH between VECTOR-PUSH-EXTEND. Such a macro +;;; should probably be based on the VECTOR-PUSH-EXTEND code (which is +;;; new ca. sbcl-0.7.0) rather than the VECTOR-PUSH code (which dates +;;; back to CMU CL). (defun vector-push (new-el array) #!+sb-doc "Attempt to set the element of ARRAY designated by its fill pointer @@ -663,9 +702,6 @@ vector &optional (extension (1+ (length vector)))) - #!+sb-doc - "This is like Vector-Push except that if the fill pointer gets too - large, the Vector is extended rather than Nil being returned." (declare (vector vector) (fixnum extension)) (let ((fill-pointer (fill-pointer vector))) (declare (fixnum fill-pointer)) @@ -677,9 +713,8 @@ (defun vector-pop (array) #!+sb-doc - "Attempts to decrease the fill pointer by 1 and return the element - pointer to by the new fill pointer. If the original value of the fill - pointer is 0, an error occurs." + "Decrease the fill pointer by 1 and return the element pointed to by the + new fill pointer." (declare (vector array)) (let ((fill-pointer (fill-pointer array))) (declare (fixnum fill-pointer)) @@ -697,7 +732,7 @@ initial-contents fill-pointer displaced-to displaced-index-offset) #!+sb-doc - "Adjusts the Array's dimensions to the given Dimensions and stuff." + "Adjust ARRAY's dimensions to the given DIMENSIONS and stuff." (let ((dimensions (if (listp dimensions) dimensions (list dimensions)))) (cond ((/= (the fixnum (length (the list dimensions))) (the fixnum (array-rank array))) @@ -838,15 +873,22 @@ (unless (array-header-p vector) (macrolet ((frob (name &rest things) `(etypecase ,name - ,@(mapcar #'(lambda (thing) - `(,(car thing) - (fill (truly-the ,(car thing) ,name) - ,(cadr thing) - :start new-length))) + ((simple-array nil (*)) (error 'cell-error + :name 'nil-array-element)) + ,@(mapcar (lambda (thing) + (destructuring-bind (type-spec fill-value) + thing + `(,type-spec + (fill (truly-the ,type-spec ,name) + ,fill-value + :start new-length)))) things)))) + ;; FIXME: The associations between vector types and initial + ;; values here are redundant with + ;; *SPECIALIZED-ARRAY-ELEMENT-TYPE-PROPERTIES*. (frob vector (simple-vector 0) - (simple-base-string #.default-init-char) + (simple-base-string #.*default-init-char-form*) (simple-bit-vector 0) ((simple-array (unsigned-byte 2) (*)) 0) ((simple-array (unsigned-byte 4) (*)) 0) @@ -936,9 +978,9 @@ (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))