1 ;;;; tests related to sequences
3 ;;;; This file is impure because we want to be able to use DEFUN.
5 ;;;; This software is part of the SBCL system. See the README file for
8 ;;;; While most of SBCL is derived from the CMU CL system, the test
9 ;;;; files (like this one) were written from scratch after the fork
12 ;;;; This software is in the public domain and is provided with
13 ;;;; absolutely no warranty. See the COPYING and CREDITS files for
14 ;;;; more information.
18 ;;; helper functions for exercising SEQUENCE code on data of many
19 ;;; specialized types, and in many different optimization scenarios
20 (defun for-every-seq-1 (base-seq snippet)
21 (dolist (seq-type '(list
24 (simple-array character 1)
26 (simple-array (signed-byte 4) 1)
27 (vector (signed-byte 4))))
28 (flet ((entirely (eltype)
29 (every (lambda (el) (typep el eltype)) base-seq)))
30 (dolist (declaredness '(nil t))
31 (dolist (optimization '(((speed 3) (space 0))
34 ((speed 0) (space 1))))
35 (let* ((seq (if (eq seq-type 'list)
36 (coerce base-seq 'list)
37 (destructuring-bind (type-first &rest type-rest)
41 (destructuring-bind (eltype one) type-rest
44 (coerce base-seq seq-type)
47 (destructuring-bind (eltype) type-rest
49 (let ((initial-element
50 (cond ((subtypep eltype 'character)
52 ((subtypep eltype 'number)
65 (lambda-expr `(lambda (seq)
67 `((declare (type ,seq-type seq))))
68 (declare (optimize ,@optimization))
70 (format t "~&~S~%" lambda-expr)
71 (multiple-value-bind (fun warnings-p failure-p)
72 (compile nil lambda-expr)
73 (when (or warnings-p failure-p)
74 (error "~@<failed compilation:~2I ~_LAMBDA-EXPR=~S ~_WARNINGS-P=~S ~_FAILURE-P=~S~:@>"
75 lambda-expr warnings-p failure-p))
76 (format t "~&~S ~S ~S ~S ~S~%"
77 base-seq snippet seq-type declaredness optimization)
78 (format t "~&(TYPEP SEQ 'SIMPLE-ARRAY)=~S~%"
79 (typep seq 'simple-array))
80 (unless (funcall fun seq)
81 (error "~@<failed test:~2I ~_BASE-SEQ=~S ~_SNIPPET=~S ~_SEQ-TYPE=~S ~_DECLAREDNESS=~S ~_OPTIMIZATION=~S~:@>"
87 (defun for-every-seq (base-seq snippets)
88 (dolist (snippet snippets)
89 (for-every-seq-1 base-seq snippet)))
91 ;;; a wrapper to hide declared type information from the compiler, so
92 ;;; we don't get stopped by compiler warnings about e.g. compiling
93 ;;; (POSITION 1 #() :KEY #'ABS) when #() has been coerced to a string.
94 (defun indiscriminate (fun)
95 (lambda (&rest rest) (apply fun rest)))
97 ;;; tests of FIND, POSITION, FIND-IF, and POSITION-IF (and a few for
98 ;;; deprecated FIND-IF-NOT and POSITION-IF-NOT too)
100 '((null (find 1 seq))
101 (null (find 1 seq :from-end t))
102 (null (position 1 seq :key (indiscriminate #'abs)))
103 (null (position nil seq :test (constantly t)))
104 (null (position nil seq :test nil))
105 (null (position nil seq :test-not nil))
106 (null (find-if #'1+ seq :key (indiscriminate #'log)))
107 (null (position-if #'identity seq :from-end t))
108 (null (find-if-not #'packagep seq))
109 (null (position-if-not #'packagep seq :key nil))))
111 '((null (find 2 seq))
112 (find 2 seq :key #'1+)
113 (find 1 seq :from-end t)
114 (null (find 1 seq :from-end t :start 1))
115 (null (find 0 seq :from-end t))
116 (eql 0 (position 1 seq :key #'abs))
117 (null (position nil seq :test 'equal))
118 (eql 1 (find-if #'1- seq :key #'log))
119 (eql 0 (position-if #'identity seq :from-end t))
120 (null (find-if-not #'sin seq))
121 (eql 0 (position-if-not #'packagep seq :key 'identity))))
122 (for-every-seq #(1 2 3 2 1)
124 (find 3 seq :from-end 'yes)
125 (eql 0 (position 0 seq :key '1-))
126 (eql 4 (position 0 seq :key '1- :from-end t))
127 (eql 2 (position 4 seq :key '1+))
128 (eql 2 (position 4 seq :key '1+ :from-end t))
129 (eql 1 (position 2 seq))
130 (eql 1 (position 2 seq :start 1))
131 (null (find 2 seq :start 1 :end 1))
132 (eql 3 (position 2 seq :start 2))
133 (eql 3 (position 2 seq :key nil :from-end t))
134 (eql 2 (position 3 seq :test '=))
135 (eql 0 (position 3 seq :test-not 'equalp))
136 (eql 2 (position 3 seq :test 'equal :from-end t))
137 (null (position 4 seq :test #'eql))
138 (null (find-if #'packagep seq))
139 (eql 1 (find-if #'plusp seq))
140 (eql 3 (position-if #'plusp seq :key #'1- :from-end t))
141 (eql 1 (position-if #'evenp seq))
142 (eql 3 (position-if #'evenp seq :from-end t))
143 (eql 2 (position-if #'plusp seq :from-end nil :key '1- :start 2))
144 (eql 3 (position-if #'plusp seq :from-end t :key '1- :start 2))
145 (null (position-if #'plusp seq :from-end t :key '1- :start 2 :end 2))
146 (null (find-if-not #'plusp seq))
147 (eql 0 (position-if-not #'evenp seq))))
148 (for-every-seq "string test"
149 '((null (find 0 seq))
150 (null (find #\D seq :key #'char-upcase))
151 (find #\E seq :key #'char-upcase)
152 (null (find #\e seq :key #'char-upcase))
153 (eql 3 (position #\i seq))
154 (eql 0 (position #\s seq :key #'char-downcase))
155 (eql 1 (position #\s seq :key #'char-downcase :test #'char/=))
156 (eql 9 (position #\s seq :from-end t :test #'char=))
157 (eql 10 (position #\s seq :from-end t :test #'char/=))
158 (eql 4 (position #\N seq :from-end t :key 'char-upcase :test #'char-equal))
159 (eql 5 (position-if (lambda (c) (equal #\g c)) seq))
160 (eql 5 (position-if (lambda (c) (equal #\g c)) seq :from-end t))
161 (find-if #'characterp seq)
162 (find-if #'(lambda (c) (typep c 'base-char)) seq :from-end t)
163 (null (find-if 'upper-case-p seq))))
166 (quit :unix-status 104)