prettier backtraces
[sbcl.git] / src / code / seq.lisp
index 96a67b3..ea6fda7 100644 (file)
           (typecase expanded-type
             (atom (cond
                     ((eq expanded-type 'string) '(vector character))
-                    ((eq expanded-type 'simple-string) '(simple-array character (*)))
+                    ((eq expanded-type 'simple-string)
+                     '(simple-array character (*)))
                     (t type)))
             (cons (cond
-                    ((eq (car expanded-type) 'string) `(vector character ,@(cdr expanded-type)))
+                    ((eq (car expanded-type) 'string)
+                     `(vector character ,@(cdr expanded-type)))
                     ((eq (car expanded-type) 'simple-string)
                      `(simple-array character ,(if (cdr expanded-type)
                                                    (cdr expanded-type)
                                                    '(*))))
-                    (t type)))
-            (t type)))
+                    (t type)))))
          (type (specifier-type adjusted-type)))
     (cond ((csubtypep type (specifier-type 'list))
            (cond
 \f
 ;;;; SUBSEQ
 ;;;;
+
+(define-array-dispatch vector-subseq-dispatch (array start end)
+  (declare (optimize speed (safety 0)))
+  (declare (type index start end))
+  (subseq array start end))
+
 ;;;; The support routines for SUBSEQ are used by compiler transforms,
 ;;;; so we worry about dealing with END being supplied or defaulting
 ;;;; to NIL at this level.
                     (end end)
                     :check-fill-pointer t
                     :force-inline t)
-    (funcall (!find-vector-subseq-fun data) data start end)))
+    (vector-subseq-dispatch data start end)))
 
 (defun list-subseq* (sequence start end)
   (declare (type list sequence)
@@ -775,7 +782,7 @@ many elements are copied."
         (let ((,sequence ,s))
           (seq-dispatch ,sequence
             (dolist (,e ,sequence ,return) ,@body)
-            (dovector (,e ,sequence ,return) ,@body)
+            (do-vector-data (,e ,sequence ,return) ,@body)
             (multiple-value-bind (state limit from-end step endp elt)
                 (sb!sequence:make-sequence-iterator ,sequence)
               (do ((state state (funcall step ,sequence state from-end)))
@@ -881,7 +888,7 @@ many elements are copied."
   (def %concatenate-to-string character)
   (def %concatenate-to-base-string base-char))
 \f
-;;;; MAP and MAP-INTO
+;;;; MAP
 
 ;;; helper functions to handle arity-1 subcases of MAP
 (declaim (ftype (function (function sequence) list) %map-list-arity-1))
@@ -1045,74 +1052,79 @@ many elements are copied."
          first-sequence
          more-sequences))
 
+;;;; MAP-INTO
+
+(defmacro map-into-lambda (sequences params &body body)
+  (check-type sequences symbol)
+  `(flet ((f ,params ,@body))
+     (declare (truly-dynamic-extent #'f))
+     ;; Note (MAP-INTO SEQ (LAMBDA () ...)) is a different animal,
+     ;; hence the awkward flip between MAP and LOOP.
+     (if ,sequences
+         (apply #'map nil #'f ,sequences)
+         (loop (f)))))
+
+(define-array-dispatch vector-map-into (data start end fun sequences)
+  (declare (optimize speed (safety 0))
+           (type index start end)
+           (type function fun)
+           (type list sequences))
+  (let ((index start))
+    (declare (type index index))
+    (block mapping
+      (map-into-lambda sequences (&rest args)
+        (declare (truly-dynamic-extent args))
+        (when (eql index end)
+          (return-from mapping))
+        (setf (aref data index) (apply fun args))
+        (incf index)))
+    index))
+
 ;;; Uses the machinery of (MAP NIL ...). For non-vectors we avoid
 ;;; computing the length of the result sequence since we can detect
 ;;; the end during mapping (if MAP even gets that far).
+;;;
+;;; For each result type, define a mapping function which is
+;;; responsible for replacing RESULT-SEQUENCE elements and for
+;;; terminating itself if the end of RESULT-SEQUENCE is reached.
+;;; The mapping function is defined with MAP-INTO-LAMBDA.
+;;;
+;;; MAP-INTO-LAMBDAs are optimized since they are the inner loops.
+;;; Because we are manually doing bounds checking with known types,
+;;; safety is turned off for vectors and lists but kept for generic
+;;; sequences.
 (defun map-into (result-sequence function &rest sequences)
-  (declare (truly-dynamic-extent sequences))
   (let ((really-fun (%coerce-callable-to-fun function)))
-    ;; For each result type, define a mapping function which is
-    ;; responsible for replacing RESULT-SEQUENCE elements and for
-    ;; terminating itself if the end of RESULT-SEQUENCE is reached.
-    ;;
-    ;; The mapping function is defined with the MAP-LAMBDA macrolet,
-    ;; whose syntax matches that of LAMBDA.
-    (macrolet ((map-lambda (params &body body)
-                 `(flet ((f ,params ,@body))
-                    (declare (truly-dynamic-extent #'f))
-                    ;; Note (MAP-INTO SEQ (LAMBDA () ...)) is a
-                    ;; different animal, hence the awkward flip
-                    ;; between MAP and LOOP.
-                    (if sequences
-                        (apply #'map nil #'f sequences)
-                        (loop (f))))))
-      ;; Optimize MAP-LAMBDAs since they are the inner loops. Because
-      ;; we are manually doing bounds checking with known types, turn
-      ;; off safety for vectors and lists but keep it for generic
-      ;; sequences.
-      (etypecase result-sequence
-        (vector
-         (locally (declare (optimize speed (safety 0)))
-           (with-array-data ((data result-sequence) (start) (end)
-                             ;; MAP-INTO ignores fill pointer when mapping
-                             :check-fill-pointer nil)
-             (let ((index start))
-               (declare (type index index))
-               (macrolet ((dispatch ()
-                            `(block mapping
-                               (map-lambda (&rest args)
-                                 (declare (truly-dynamic-extent args))
-                                 (when (eql index end)
-                                   (return-from mapping))
-                                 (setf (aref data index)
-                                       (apply really-fun args))
-                                 (incf index)))))
-                 (typecase data
-                   (simple-vector (dispatch))
-                   (otherwise (dispatch))))
-               (when (array-has-fill-pointer-p result-sequence)
-                 (setf (fill-pointer result-sequence) (- index start)))))))
-        (list
-         (let ((node result-sequence))
-           (declare (type list node))
-           (map-lambda (&rest args)
-             (declare (truly-dynamic-extent args) (optimize speed (safety 0)))
-             (when (null node)
-               (return-from map-into result-sequence))
-             (setf (car node) (apply really-fun args))
-             (setf node (cdr node)))))
-        (sequence
-         (multiple-value-bind (iter limit from-end)
-             (sb!sequence:make-sequence-iterator result-sequence)
-           (map-lambda (&rest args)
-             (declare (truly-dynamic-extent args) (optimize speed))
-             (when (sb!sequence:iterator-endp result-sequence
-                                              iter limit from-end)
-               (return-from map-into result-sequence))
-             (setf (sb!sequence:iterator-element result-sequence iter)
-                   (apply really-fun args))
-             (setf iter (sb!sequence:iterator-step result-sequence
-                                                   iter from-end))))))))
+    (etypecase result-sequence
+      (vector
+       (with-array-data ((data result-sequence) (start) (end)
+                         ;; MAP-INTO ignores fill pointer when mapping
+                         :check-fill-pointer nil)
+         (let ((new-end (vector-map-into data start end really-fun sequences)))
+           (when (array-has-fill-pointer-p result-sequence)
+             (setf (fill-pointer result-sequence) (- new-end start))))))
+      (list
+       (let ((node result-sequence))
+         (declare (type list node))
+         (map-into-lambda sequences (&rest args)
+           (declare (truly-dynamic-extent args)
+                    (optimize speed (safety 0)))
+           (when (null node)
+             (return-from map-into result-sequence))
+           (setf (car node) (apply really-fun args))
+           (setf node (cdr node)))))
+      (sequence
+       (multiple-value-bind (iter limit from-end)
+           (sb!sequence:make-sequence-iterator result-sequence)
+         (map-into-lambda sequences (&rest args)
+           (declare (truly-dynamic-extent args) (optimize speed))
+           (when (sb!sequence:iterator-endp result-sequence
+                                            iter limit from-end)
+             (return-from map-into result-sequence))
+           (setf (sb!sequence:iterator-element result-sequence iter)
+                 (apply really-fun args))
+           (setf iter (sb!sequence:iterator-step result-sequence
+                                                           iter from-end)))))))
   result-sequence)
 \f
 ;;;; quantifiers
@@ -1172,7 +1184,7 @@ many elements are copied."
                 ;; from the old seq.lisp into target-seq.lisp.
                 (define-compiler-macro ,name (pred first-seq &rest more-seqs)
                   (let ((elements (make-gensym-list (1+ (length more-seqs))))
-                        (blockname (gensym "BLOCK")))
+                        (blockname (sb!xc:gensym "BLOCK")))
                     (once-only ((pred pred))
                       `(block ,blockname
                          (map nil
@@ -2224,11 +2236,12 @@ many elements are copied."
                          ((simple-array base-char (*)) (frob2))
                          ,@(when bit-frob
                              `((simple-bit-vector
-                                (if (and (eq #'identity key)
+                                (if (and (typep item 'bit)
+                                         (eq #'identity key)
                                          (or (eq #'eq test)
                                              (eq #'eql test)
                                              (eq #'equal test)))
-                                    (let ((p (%bit-position (the bit item) sequence
+                                    (let ((p (%bit-position item sequence
                                                             from-end start end)))
                                       (if p
                                           (values item p)