Nicer docstring syntax for case-lambda.
[bpt/guile.git] / test-suite / tests / optargs.test
CommitLineData
025f75b4
MV
1;;;; optargs.test --- test suite for optional arg processing -*- scheme -*-
2;;;; Matthias Koeppe <mkoeppe@mail.math.uni-magdeburg.de> --- June 2001
3;;;;
581f410f 4;;;; Copyright (C) 2001, 2006, 2009, 2010, 2013 Free Software Foundation, Inc.
025f75b4 5;;;;
53befeb7
NJ
6;;;; This library is free software; you can redistribute it and/or
7;;;; modify it under the terms of the GNU Lesser General Public
8;;;; License as published by the Free Software Foundation; either
9;;;; version 3 of the License, or (at your option) any later version.
025f75b4 10;;;;
53befeb7 11;;;; This library is distributed in the hope that it will be useful,
025f75b4 12;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
53befeb7
NJ
13;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14;;;; Lesser General Public License for more details.
025f75b4 15;;;;
53befeb7
NJ
16;;;; You should have received a copy of the GNU Lesser General Public
17;;;; License along with this library; if not, write to the Free Software
18;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
025f75b4 19
560434b3 20(define-module (test-suite test-optargs)
7ab42fa2
AW
21 #:use-module (test-suite lib)
22 #:use-module (system base compile)
23 #:use-module (ice-9 optargs))
24
581f410f
AW
25(define exception:invalid-keyword
26 '(keyword-argument-error . "Invalid keyword"))
27
ee2a69f5 28(define exception:unrecognized-keyword
f6a8e791 29 '(keyword-argument-error . "Unrecognized keyword"))
ee2a69f5
LC
30
31(define exception:extraneous-arguments
f6a8e791
AW
32 ;; Message depends on whether we use the interpreter or VM, and on the
33 ;; evenness of the number of extra arguments (!).
34 ;'(keyword-argument-error . ".*")
35 '(#t . ".*"))
ee2a69f5 36
7ab42fa2
AW
37(define-syntax c&e
38 (syntax-rules (pass-if pass-if-exception)
39 ((_ (pass-if test-name exp))
40 (begin (pass-if (string-append test-name " (eval)")
41 (primitive-eval 'exp))
42 (pass-if (string-append test-name " (compile)")
43 (compile 'exp #:to 'value #:env (current-module)))))
44 ((_ (pass-if-exception test-name exc exp))
45 (begin (pass-if-exception (string-append test-name " (eval)")
46 exc (primitive-eval 'exp))
47 (pass-if-exception (string-append test-name " (compile)")
48 exc (compile 'exp #:to 'value
49 #:env (current-module)))))))
50
51(define-syntax with-test-prefix/c&e
52 (syntax-rules ()
53 ((_ section-name exp ...)
54 (with-test-prefix section-name (c&e exp) ...))))
55
56(with-test-prefix/c&e "optional argument processing"
025f75b4 57 (pass-if "local defines work with optional arguments"
560434b3
DH
58 (eval '(begin
59 (define* (test-1 #:optional (x 0))
60 (define d 1) ; local define
61 #t)
62 (false-if-exception (test-1)))
63 (interaction-environment))))
927a122d
KR
64
65;;;
66;;; let-keywords
67;;;
68
7ab42fa2 69(with-test-prefix/c&e "let-keywords"
927a122d
KR
70
71 ;; in guile 1.6.4 and earlier, an empty binding list only used `begin',
72 ;; which caused apparently internal defines to "leak" out into the
73 ;; encompasing environment
74 (pass-if-exception "empty bindings internal defines leaking out"
75 exception:unbound-var
76 (let ((rest '()))
77 (let-keywords rest #f ()
78 (define localvar #f)
79 #f)
80 localvar))
81
82 (pass-if "one key"
83 (let-keywords '(#:foo 123) #f (foo)
84 (= foo 123))))
85
86;;;
87;;; let-keywords*
88;;;
89
7ab42fa2 90(with-test-prefix/c&e "let-keywords*"
927a122d
KR
91
92 ;; in guile 1.6.4 and earlier, an empty binding list only used `begin',
93 ;; which caused apparently internal defines to "leak" out into the
94 ;; encompasing environment
95 (pass-if-exception "empty bindings internal defines leaking out"
96 exception:unbound-var
97 (let ((rest '()))
98 (let-keywords* rest #f ()
99 (define localvar #f)
100 #f)
101 localvar))
102
103 (pass-if "one key"
104 (let-keywords* '(#:foo 123) #f (foo)
105 (= foo 123))))
106
107;;;
108;;; let-optional
109;;;
110
7ab42fa2 111(with-test-prefix/c&e "let-optional"
927a122d
KR
112
113 ;; in guile 1.6.4 and earlier, an empty binding list only used `begin',
114 ;; which caused apparently internal defines to "leak" out into the
115 ;; encompasing environment
116 (pass-if-exception "empty bindings internal defines leaking out"
117 exception:unbound-var
118 (let ((rest '()))
119 (let-optional rest ()
120 (define localvar #f)
121 #f)
122 localvar))
123
124 (pass-if "one var"
125 (let ((rest '(123)))
126 (let-optional rest ((foo 999))
127 (= foo 123)))))
128
129;;;
130;;; let-optional*
131;;;
132
7ab42fa2 133(with-test-prefix/c&e "let-optional*"
927a122d
KR
134
135 ;; in guile 1.6.4 and earlier, an empty binding list only used `begin',
136 ;; which caused apparently internal defines to "leak" out into the
137 ;; encompasing environment
138 (pass-if-exception "empty bindings internal defines leaking out"
139 exception:unbound-var
140 (let ((rest '()))
141 (let-optional* rest ()
142 (define localvar #f)
143 #f)
144 localvar))
145
146 (pass-if "one var"
147 (let ((rest '(123)))
148 (let-optional* rest ((foo 999))
149 (= foo 123)))))
7ab42fa2
AW
150
151(define* (foo a b #:optional c (d 1) (e c) f #:key g (h a) (i r) #:rest r)
152 (list a b c d e f g h i r))
153
154;; So we could use lots more tests here, but the fact that lambda* is in
155;; the compiler, and the compiler compiles itself, using the evaluator
156;; (when bootstrapping) and compiled code (when doing a partial rebuild)
157;; makes me a bit complacent.
158(with-test-prefix/c&e "define*"
159 (pass-if "the whole enchilada"
160 (equal? (foo 1 2)
ee2a69f5
LC
161 '(1 2 #f 1 #f #f #f 1 () ())))
162
163 (pass-if-exception "extraneous arguments"
164 exception:extraneous-arguments
165 (let ((f (lambda* (#:key x) x)))
166 (f 1 2 #:x 'x)))
167
168 (pass-if-exception "unrecognized keyword"
169 exception:unrecognized-keyword
170 (let ((f (lambda* (#:key x) x)))
171 (f #:y 'not-recognized)))
172
173 (pass-if "rest given before keywords"
174 ;; Passing the rest argument before the keyword arguments should not
175 ;; prevent keyword argument binding.
176 (let ((f (lambda* (#:key x y z #:rest r) (list x y z r))))
177 (equal? (f 1 2 3 #:x 'x #:z 'z)
178 '(x #f z (1 2 3 #:x x #:z z))))))
aac006dd 179
a310a1d1 180(with-test-prefix/c&e "lambda* inits"
9a9d82c2
AW
181 (pass-if "can bind lexicals within inits"
182 (begin
d8a071fc
AW
183 (define qux
184 (lambda* (#:optional a #:key (b (or a 13) #:a))
185 b))
9a9d82c2
AW
186 #t))
187 (pass-if "testing qux"
188 (and (equal? (qux) 13)
189 (equal? (qux 1) 1)
84b67e19
AW
190 (equal? (qux #:a 2) 2)))
191 (pass-if "nested lambda* with optional"
192 (begin
193 (define (foo x)
194 (define baz x)
195 (define* (bar #:optional (y baz))
196 (or (zero? y) (bar (1- y))))
197 (bar))
198 (foo 10)))
199 (pass-if "nested lambda* with key"
200 (begin
201 (define (foo x)
202 (define baz x)
203 (define* (bar #:key (y baz))
204 (or (zero? y) (bar #:y (1- y))))
205 (bar))
206 (foo 10))))
207
9a9d82c2 208
aac006dd
AW
209(with-test-prefix/c&e "defmacro*"
210 (pass-if "definition"
211 (begin
212 (defmacro* transmogrify (a #:optional (b 10))
213 `(,a ,b))
214 #t))
215
216 (pass-if "explicit arg"
217 (equal? (transmogrify quote 5)
218 5))
219
220 (pass-if "default arg"
221 (equal? (transmogrify quote)
222 10)))
581f410f 223
19113f1c
AW
224(with-test-prefix/c&e "case-lambda"
225 (pass-if-exception "no clauses, no args" exception:wrong-num-args
226 ((case-lambda)))
227
228 (pass-if-exception "no clauses, args" exception:wrong-num-args
0426b3f8
MW
229 ((case-lambda) 1))
230
231 (pass-if "docstring"
232 (equal? "docstring test"
233 (procedure-documentation
234 (case-lambda
235 "docstring test"
236 (() 0)
237 ((x) 1))))))
19113f1c 238
581f410f 239(with-test-prefix/c&e "case-lambda*"
19113f1c
AW
240 (pass-if-exception "no clauses, no args" exception:wrong-num-args
241 ((case-lambda*)))
242
243 (pass-if-exception "no clauses, args" exception:wrong-num-args
244 ((case-lambda*) 1))
245
0426b3f8
MW
246 (pass-if "docstring"
247 (equal? "docstring test"
248 (procedure-documentation
249 (case-lambda*
250 "docstring test"
251 (() 0)
252 ((x) 1)))))
253
581f410f
AW
254 (pass-if "unambiguous"
255 ((case-lambda*
256 ((a b) #t)
257 ((a) #f))
258 1 2))
259
260 (pass-if "unambiguous (reversed)"
261 ((case-lambda*
262 ((a) #f)
263 ((a b) #t))
264 1 2))
265
266 (pass-if "optionals (order disambiguates)"
267 ((case-lambda*
268 ((a #:optional b) #t)
269 ((a b) #f))
270 1 2))
271
272 (pass-if "optionals (order disambiguates (2))"
273 ((case-lambda*
274 ((a b) #t)
275 ((a #:optional b) #f))
276 1 2))
277
278 (pass-if "optionals (one arg)"
279 ((case-lambda*
280 ((a b) #f)
281 ((a #:optional b) #t))
282 1))
283
284 (pass-if "optionals (one arg (2))"
285 ((case-lambda*
286 ((a #:optional b) #t)
287 ((a b) #f))
288 1))
289
290 (pass-if "keywords without keyword"
291 ((case-lambda*
292 ((a #:key c) #t)
293 ((a b) #f))
294 1))
295
296 (pass-if "keywords with keyword"
297 ((case-lambda*
298 ((a #:key c) #t)
299 ((a b) #f))
300 1 #:c 2))
301
302 (pass-if "keywords (too many positionals)"
303 ((case-lambda*
304 ((a #:key c) #f)
305 ((a b) #t))
306 1 2))
307
308 (pass-if "keywords (order disambiguates)"
309 ((case-lambda*
310 ((a #:key c) #t)
311 ((a b c) #f))
312 1 #:c 2))
313
314 (pass-if "keywords (order disambiguates (2))"
315 ((case-lambda*
316 ((a b c) #t)
317 ((a #:key c) #f))
318 1 #:c 2)))