0.6.9.20:
[sbcl.git] / tests / seq.impure.lisp
1 ;;;; tests related to sequences
2
3 ;;;; This file is impure because we want to be able to use DEFUN.
4
5 ;;;; This software is part of the SBCL system. See the README file for
6 ;;;; more information.
7 ;;;;
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
10 ;;;; from CMU CL.
11 ;;;; 
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.
15
16 (in-package :cl-user)
17
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
22                       (simple-array t 1)
23                       (vector t)
24                       (simple-array character 1)
25                       (vector character)
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))
32                                 ((speed 2) (space 2))
33                                 ((speed 1) (space 2))
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)
38                               seq-type
39                             (ecase type-first
40                               (simple-array
41                                (destructuring-bind (eltype one) type-rest
42                                  (assert (= one 1))
43                                  (if (entirely eltype)
44                                      (coerce base-seq seq-type)
45                                      (return))))
46                               (vector
47                                (destructuring-bind (eltype) type-rest
48                                  (if (entirely eltype)
49                                      (replace (make-array (length base-seq)
50                                                           :element-type eltype
51                                                           :adjustable t)
52                                               base-seq)
53                                      (return))))))))
54                  (lambda-expr `(lambda (seq)
55                                  ,@(when declaredness
56                                      `((declare (type ,seq-type seq))))
57                                  (declare (optimize ,@optimization))
58                                  ,snippet)))
59             (multiple-value-bind (fun warnings-p failure-p)
60                 (compile nil lambda-expr)
61               (when (or warnings-p failure-p)
62                 (error "~@<failed compilation:~2I ~_WARNINGS-P=~S ~_FAILURE-P=~S ~_LAMBDA-EXPR=~S~:@>" lambda-expr))
63               (unless (funcall fun seq)
64                 (error "~@<failed test:~2I ~_BASE-SEQ=~S ~_SNIPPET=~S ~_SEQ-TYPE=~S ~_DECLAREDNESS=~S ~_OPTIMIZATION=~S~:@>"
65                        base-seq
66                        snippet
67                        seq-type
68                        declaredness
69                        optimization)))))))))
70 (defun for-every-seq (base-seq snippets)
71   (dolist (snippet snippets)
72     (for-every-seq-1 base-seq snippet)))
73                 
74 ;;; tests of FIND, POSITION, FIND-IF, and POSITION-IF (and a few for
75 ;;; deprecated FIND-IF-NOT and POSITION-IF-NOT too)
76 (for-every-seq #()
77   '((null (find 1 seq))
78     (null (find 1 seq :from-end t))
79     (null (position 1 seq :key #'abs))
80     (null (position nil seq :test (constantly t)))
81     (null (position nil seq :test nil))
82     (null (position nil seq :test-not nil))
83     (null (find-if #'1+ seq :key #'log))
84     (null (position-if #'identity seq :from-end t))
85     (null (find-if-not #'packagep seq))
86     (null (position-if-not #'packagep seq :key nil))))
87 (for-every-seq #(1)
88   '((null (find 2 seq))
89     (find 2 seq :key #'1+)
90     (find 1 seq :from-end t)
91     (null (find 0 seq :from-end t))
92     (eql 0 (position 1 seq :key #'abs))
93     (null (position nil seq :test 'equal))
94     (eql 1 (find-if #'1- seq :key #'log))
95     (eql 0 (position-if #'identity seq :from-end t))
96     (null (find-if-not #'sin seq))
97     (eql 0 (position-if-not #'packagep seq :key 'identity))))
98 (for-every-seq #(1 2 3 2 1)
99   '((find 3 seq)
100     (find 3 seq :from-end 'yes)
101     (eql 0 (position 0 seq :key '1-))
102     (eql 4 (position 0 seq :key '1- :from-end t))
103     (eql 2 (position 4 seq :key '1+))
104     (eql 2 (position 4 seq :key '1+ :from-end t))
105     (eql 1 (position 2 seq))
106     (eql 3 (position 2 seq :key nil :from-end t))
107     (eql 2 (position 3 seq :test '=))
108     (eql 0 (position 3 seq :test-not 'equalp))
109     (eql 2 (position 3 seq :test 'equal :from-end t))
110     (null (position 4 seq :test #'eql))
111     (null (find-if #'packagep seq))
112     (eql 1 (find-if #'plusp seq))
113     (eql 3 (position-if #'plusp seq :key #'1- :from-end t))
114     (eql 1 (position-if #'evenp seq))
115     (eql 3 (position-if #'evenp seq :from-end t))
116     (null (find-if-not #'plusp seq))
117     (eql 0 (position-if-not #'evenp seq))))
118 (for-every-seq "string test"
119   '((null (find 0 seq))
120     (null (find #\D seq :key #'char-upcase))
121     (find #\E seq :key #'char-upcase)
122     (null (find #\e seq :key #'char-upcase))
123     (eql 3 (position #\i seq))
124     (eql 0 (position #\s seq :key #'char-downcase))
125     (eql 1 (position #\s seq :key #'char-downcase :test #'char/=))
126     (eql 9 (position #\s seq :from-end t :test #'char=))
127     (eql 10 (position #\s seq :from-end t :test #'char/=))
128     (eql 4 (position #\N seq :from-end t :key 'char-upcase :test #'char-equal))
129     (eql 5 (position-if (lambda (c) (equal #\g c)) seq))
130     (eql 5 (position-if (lambda (c) (equal #\g c)) seq :from-end t))
131     (find-if #'characterp seq)
132     (find-if #'(lambda (c) (typep c 'base-char)) seq :from-end t)
133     (null (find-if 'upper-case-p seq))))
134
135 ;;; success
136 (quit :unix-status 104)