1 ;;;; tree-il.test --- test suite for compiling tree-il -*- scheme -*-
2 ;;;; Andy Wingo <wingo@pobox.com> --- May 2009
4 ;;;; Copyright (C) 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
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.
11 ;;;; This library is distributed in the hope that it will be useful,
12 ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ;;;; Lesser General Public License for more details.
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
20 (define-module (test-suite tree-il)
21 #:use-module (test-suite lib)
22 #:use-module (system base compile)
23 #:use-module (system base pmatch)
24 #:use-module (system base message)
25 #:use-module (language tree-il)
26 #:use-module (language tree-il primitives)
27 #:use-module (language glil)
28 #:use-module (srfi srfi-13))
30 ;; Of course, the GLIL that is emitted depends on the source info of the
31 ;; input. Here we're not concerned about that, so we strip source
32 ;; information from the incoming tree-il.
34 (define (strip-source x)
35 (post-order! (lambda (x) (set! (tree-il-src x) #f))
38 (define-syntax assert-tree-il->glil
39 (syntax-rules (with-partial-evaluation without-partial-evaluation
41 ((_ with-partial-evaluation in pat test ...)
42 (assert-tree-il->glil with-options (#:partial-eval? #t)
44 ((_ without-partial-evaluation in pat test ...)
45 (assert-tree-il->glil with-options (#:partial-eval? #f)
47 ((_ with-options opts in pat test ...)
50 (let ((glil (unparse-glil
51 (compile (strip-source (parse-tree-il exp))
52 #:from 'tree-il #:to 'glil
55 (pat (guard test ...) #t)
58 (assert-tree-il->glil with-partial-evaluation
61 (define-syntax pass-if-tree-il->scheme
64 (assert-scheme->tree-il->scheme in pat #t))
67 (pmatch (tree-il->scheme
68 (compile 'in #:from 'scheme #:to 'tree-il))
69 (pat (guard guard-exp) #t)
73 (with-test-prefix "tree-il->scheme"
74 (pass-if-tree-il->scheme
75 (case-lambda ((a) a) ((b c) (list b c)))
76 (case-lambda ((,a) ,a1) ((,b ,c) (list ,b1 ,c1)))
77 (and (eq? a a1) (eq? b b1) (eq? c c1))))
79 (with-test-prefix "void"
82 (program () (std-prelude 0 0 #f) (label _) (void) (call return 1)))
84 (begin (void) (const 1))
85 (program () (std-prelude 0 0 #f) (label _) (const 1) (call return 1)))
87 (primcall + (void) (const 1))
88 (program () (std-prelude 0 0 #f) (label _) (void) (call add1 1) (call return 1))))
90 (with-test-prefix "application"
92 (call (toplevel foo) (const 1))
93 (program () (std-prelude 0 0 #f) (label _) (toplevel ref foo) (const 1) (call tail-call 1)))
95 (begin (call (toplevel foo) (const 1)) (void))
96 (program () (std-prelude 0 0 #f) (label _) (call new-frame 0) (toplevel ref foo) (const 1) (mv-call 1 ,l1)
97 (call drop 1) (branch br ,l2)
98 (label ,l3) (mv-bind 0 #f)
100 (void) (call return 1))
101 (and (eq? l1 l3) (eq? l2 l4)))
102 (assert-tree-il->glil
103 (call (toplevel foo) (call (toplevel bar)))
104 (program () (std-prelude 0 0 #f) (label _) (toplevel ref foo) (call new-frame 0) (toplevel ref bar) (call call 0)
105 (call tail-call 1))))
107 (with-test-prefix "conditional"
108 (assert-tree-il->glil
109 (if (toplevel foo) (const 1) (const 2))
110 (program () (std-prelude 0 0 #f) (label _) (toplevel ref foo) (branch br-if-not ,l1)
111 (const 1) (call return 1)
112 (label ,l2) (const 2) (call return 1))
115 (assert-tree-il->glil without-partial-evaluation
116 (begin (if (toplevel foo) (const 1) (const 2)) (const #f))
117 (program () (std-prelude 0 0 #f) (label _) (toplevel ref foo) (branch br-if-not ,l1) (branch br ,l2)
118 (label ,l3) (label ,l4) (const #f) (call return 1))
119 (eq? l1 l3) (eq? l2 l4))
121 (assert-tree-il->glil
122 (primcall null? (if (toplevel foo) (const 1) (const 2)))
123 (program () (std-prelude 0 0 #f) (label _) (toplevel ref foo) (branch br-if-not ,l1)
124 (const 1) (branch br ,l2)
125 (label ,l3) (const 2) (label ,l4)
126 (call null? 1) (call return 1))
127 (eq? l1 l3) (eq? l2 l4)))
129 (with-test-prefix "primitive-ref"
130 (assert-tree-il->glil
132 (program () (std-prelude 0 0 #f) (label _) (toplevel ref +) (call return 1)))
134 (assert-tree-il->glil
135 (begin (primitive +) (const #f))
136 (program () (std-prelude 0 0 #f) (label _) (const #f) (call return 1)))
138 (assert-tree-il->glil
139 (primcall null? (primitive +))
140 (program () (std-prelude 0 0 #f) (label _) (toplevel ref +) (call null? 1)
143 (with-test-prefix "lexical refs"
144 (assert-tree-il->glil without-partial-evaluation
145 (let (x) (y) ((const 1)) (lexical x y))
146 (program () (std-prelude 0 1 #f) (label _)
147 (const 1) (bind (x #f 0)) (lexical #t #f set 0)
148 (lexical #t #f ref 0) (call return 1)
151 (assert-tree-il->glil without-partial-evaluation
152 (let (x) (y) ((const 1)) (begin (lexical x y) (const #f)))
153 (program () (std-prelude 0 1 #f) (label _)
154 (const 1) (bind (x #f 0)) (lexical #t #f set 0)
155 (const #f) (call return 1)
158 (assert-tree-il->glil without-partial-evaluation
159 (let (x) (y) ((const 1)) (primcall null? (lexical x y)))
160 (program () (std-prelude 0 1 #f) (label _)
161 (const 1) (bind (x #f 0)) (lexical #t #f set 0)
162 (lexical #t #f ref 0) (call null? 1) (call return 1)
165 (with-test-prefix "lexical sets"
166 (assert-tree-il->glil
167 ;; unreferenced sets may be optimized away -- make sure they are ref'd
168 (let (x) (y) ((const 1))
169 (set! (lexical x y) (primcall 1+ (lexical x y))))
170 (program () (std-prelude 0 1 #f) (label _)
171 (const 1) (bind (x #t 0)) (lexical #t #t box 0)
172 (lexical #t #t ref 0) (call add1 1) (lexical #t #t set 0)
173 (void) (call return 1)
176 (assert-tree-il->glil
177 (let (x) (y) ((const 1))
178 (begin (set! (lexical x y) (primcall 1+ (lexical x y)))
180 (program () (std-prelude 0 1 #f) (label _)
181 (const 1) (bind (x #t 0)) (lexical #t #t box 0)
182 (lexical #t #t ref 0) (call add1 1) (lexical #t #t set 0)
183 (lexical #t #t ref 0) (call return 1)
186 (assert-tree-il->glil
187 (let (x) (y) ((const 1))
189 (set! (lexical x y) (primcall 1+ (lexical x y)))))
190 (program () (std-prelude 0 1 #f) (label _)
191 (const 1) (bind (x #t 0)) (lexical #t #t box 0)
192 (lexical #t #t ref 0) (call add1 1) (lexical #t #t set 0) (void)
193 (call null? 1) (call return 1)
196 (with-test-prefix "module refs"
197 (assert-tree-il->glil
199 (program () (std-prelude 0 0 #f) (label _)
200 (module public ref (foo) bar)
203 (assert-tree-il->glil
204 (begin (@ (foo) bar) (const #f))
205 (program () (std-prelude 0 0 #f) (label _)
206 (module public ref (foo) bar) (call drop 1)
207 (const #f) (call return 1)))
209 (assert-tree-il->glil
210 (primcall null? (@ (foo) bar))
211 (program () (std-prelude 0 0 #f) (label _)
212 (module public ref (foo) bar)
213 (call null? 1) (call return 1)))
215 (assert-tree-il->glil
217 (program () (std-prelude 0 0 #f) (label _)
218 (module private ref (foo) bar)
221 (assert-tree-il->glil
222 (begin (@@ (foo) bar) (const #f))
223 (program () (std-prelude 0 0 #f) (label _)
224 (module private ref (foo) bar) (call drop 1)
225 (const #f) (call return 1)))
227 (assert-tree-il->glil
228 (primcall null? (@@ (foo) bar))
229 (program () (std-prelude 0 0 #f) (label _)
230 (module private ref (foo) bar)
231 (call null? 1) (call return 1))))
233 (with-test-prefix "module sets"
234 (assert-tree-il->glil
235 (set! (@ (foo) bar) (const 2))
236 (program () (std-prelude 0 0 #f) (label _)
237 (const 2) (module public set (foo) bar)
238 (void) (call return 1)))
240 (assert-tree-il->glil
241 (begin (set! (@ (foo) bar) (const 2)) (const #f))
242 (program () (std-prelude 0 0 #f) (label _)
243 (const 2) (module public set (foo) bar)
244 (const #f) (call return 1)))
246 (assert-tree-il->glil
247 (primcall null? (set! (@ (foo) bar) (const 2)))
248 (program () (std-prelude 0 0 #f) (label _)
249 (const 2) (module public set (foo) bar)
250 (void) (call null? 1) (call return 1)))
252 (assert-tree-il->glil
253 (set! (@@ (foo) bar) (const 2))
254 (program () (std-prelude 0 0 #f) (label _)
255 (const 2) (module private set (foo) bar)
256 (void) (call return 1)))
258 (assert-tree-il->glil
259 (begin (set! (@@ (foo) bar) (const 2)) (const #f))
260 (program () (std-prelude 0 0 #f) (label _)
261 (const 2) (module private set (foo) bar)
262 (const #f) (call return 1)))
264 (assert-tree-il->glil
265 (primcall null? (set! (@@ (foo) bar) (const 2)))
266 (program () (std-prelude 0 0 #f) (label _)
267 (const 2) (module private set (foo) bar)
268 (void) (call null? 1) (call return 1))))
270 (with-test-prefix "toplevel refs"
271 (assert-tree-il->glil
273 (program () (std-prelude 0 0 #f) (label _)
277 (assert-tree-il->glil without-partial-evaluation
278 (begin (toplevel bar) (const #f))
279 (program () (std-prelude 0 0 #f) (label _)
280 (toplevel ref bar) (call drop 1)
281 (const #f) (call return 1)))
283 (assert-tree-il->glil
284 (primcall null? (toplevel bar))
285 (program () (std-prelude 0 0 #f) (label _)
287 (call null? 1) (call return 1))))
289 (with-test-prefix "toplevel sets"
290 (assert-tree-il->glil
291 (set! (toplevel bar) (const 2))
292 (program () (std-prelude 0 0 #f) (label _)
293 (const 2) (toplevel set bar)
294 (void) (call return 1)))
296 (assert-tree-il->glil
297 (begin (set! (toplevel bar) (const 2)) (const #f))
298 (program () (std-prelude 0 0 #f) (label _)
299 (const 2) (toplevel set bar)
300 (const #f) (call return 1)))
302 (assert-tree-il->glil
303 (primcall null? (set! (toplevel bar) (const 2)))
304 (program () (std-prelude 0 0 #f) (label _)
305 (const 2) (toplevel set bar)
306 (void) (call null? 1) (call return 1))))
308 (with-test-prefix "toplevel defines"
309 (assert-tree-il->glil
310 (define bar (const 2))
311 (program () (std-prelude 0 0 #f) (label _)
312 (const 2) (toplevel define bar)
313 (void) (call return 1)))
315 (assert-tree-il->glil
316 (begin (define bar (const 2)) (const #f))
317 (program () (std-prelude 0 0 #f) (label _)
318 (const 2) (toplevel define bar)
319 (const #f) (call return 1)))
321 (assert-tree-il->glil
322 (primcall null? (define bar (const 2)))
323 (program () (std-prelude 0 0 #f) (label _)
324 (const 2) (toplevel define bar)
325 (void) (call null? 1) (call return 1))))
327 (with-test-prefix "constants"
328 (assert-tree-il->glil
330 (program () (std-prelude 0 0 #f) (label _)
331 (const 2) (call return 1)))
333 (assert-tree-il->glil
334 (begin (const 2) (const #f))
335 (program () (std-prelude 0 0 #f) (label _)
336 (const #f) (call return 1)))
338 (assert-tree-il->glil
339 ;; This gets simplified by `peval'.
340 (primcall null? (const 2))
341 (program () (std-prelude 0 0 #f) (label _)
342 (const #f) (call return 1))))
344 (with-test-prefix "letrec"
345 ;; simple bindings -> let
346 (assert-tree-il->glil without-partial-evaluation
347 (letrec (x y) (x1 y1) ((const 10) (const 20))
348 (call (toplevel foo) (lexical x x1) (lexical y y1)))
349 (program () (std-prelude 0 2 #f) (label _)
350 (const 10) (const 20)
351 (bind (x #f 0) (y #f 1))
352 (lexical #t #f set 1) (lexical #t #f set 0)
354 (lexical #t #f ref 0) (lexical #t #f ref 1)
358 ;; complex bindings -> box and set! within let
359 (assert-tree-il->glil without-partial-evaluation
360 (letrec (x y) (x1 y1) ((call (toplevel foo)) (call (toplevel bar)))
361 (primcall + (lexical x x1) (lexical y y1)))
362 (program () (std-prelude 0 4 #f) (label _)
363 (void) (void) ;; what are these?
364 (bind (x #t 0) (y #t 1))
365 (lexical #t #t box 1) (lexical #t #t box 0)
366 (call new-frame 0) (toplevel ref foo) (call call 0)
367 (call new-frame 0) (toplevel ref bar) (call call 0)
368 (bind (x #f 2) (y #f 3)) (lexical #t #f set 3) (lexical #t #f set 2)
369 (lexical #t #f ref 2) (lexical #t #t set 0)
370 (lexical #t #f ref 3) (lexical #t #t set 1)
371 (void) (lexical #t #f set 2) (void) (lexical #t #f set 3) ;; clear bindings
373 (lexical #t #t ref 0) (lexical #t #t ref 1)
374 (call add 2) (call return 1) (unbind)))
376 ;; complex bindings in letrec* -> box and set! in order
377 (assert-tree-il->glil without-partial-evaluation
378 (letrec* (x y) (x1 y1) ((call (toplevel foo)) (call (toplevel bar)))
379 (primcall + (lexical x x1) (lexical y y1)))
380 (program () (std-prelude 0 2 #f) (label _)
381 (void) (void) ;; what are these?
382 (bind (x #t 0) (y #t 1))
383 (lexical #t #t box 1) (lexical #t #t box 0)
384 (call new-frame 0) (toplevel ref foo) (call call 0)
385 (lexical #t #t set 0)
386 (call new-frame 0) (toplevel ref bar) (call call 0)
387 (lexical #t #t set 1)
388 (lexical #t #t ref 0)
389 (lexical #t #t ref 1)
390 (call add 2) (call return 1) (unbind)))
392 ;; simple bindings in letrec* -> equivalent to letrec
393 (assert-tree-il->glil without-partial-evaluation
394 (letrec* (x y) (xx yy) ((const 1) (const 2))
396 (program () (std-prelude 0 1 #f) (label _)
398 (bind (y #f 0)) ;; X is removed, and Y is unboxed
399 (lexical #t #f set 0)
400 (lexical #t #f ref 0)
401 (call return 1) (unbind))))
403 (with-test-prefix "lambda"
404 (assert-tree-il->glil
406 (lambda-case (((x) #f #f #f () (y)) (const 2)) #f))
407 (program () (std-prelude 0 0 #f) (label _)
408 (program () (std-prelude 1 1 #f)
409 (bind (x #f 0)) (label _)
410 (const 2) (call return 1) (unbind))
413 (assert-tree-il->glil
415 (lambda-case (((x y) #f #f #f () (x1 y1))
418 (program () (std-prelude 0 0 #f) (label _)
419 (program () (std-prelude 2 2 #f)
420 (bind (x #f 0) (y #f 1)) (label _)
421 (const 2) (call return 1)
425 (assert-tree-il->glil
427 (lambda-case ((() #f x #f () (y)) (const 2))
429 (program () (std-prelude 0 0 #f) (label _)
430 (program () (opt-prelude 0 0 0 1 #f)
431 (bind (x #f 0)) (label _)
432 (const 2) (call return 1)
436 (assert-tree-il->glil
438 (lambda-case (((x) #f x1 #f () (y y1)) (const 2))
440 (program () (std-prelude 0 0 #f) (label _)
441 (program () (opt-prelude 1 0 1 2 #f)
442 (bind (x #f 0) (x1 #f 1)) (label _)
443 (const 2) (call return 1)
447 (assert-tree-il->glil
449 (lambda-case (((x) #f x1 #f () (y y1)) (lexical x y))
451 (program () (std-prelude 0 0 #f) (label _)
452 (program () (opt-prelude 1 0 1 2 #f)
453 (bind (x #f 0) (x1 #f 1)) (label _)
454 (lexical #t #f ref 0) (call return 1)
458 (assert-tree-il->glil
460 (lambda-case (((x) #f x1 #f () (y y1)) (lexical x1 y1))
462 (program () (std-prelude 0 0 #f) (label _)
463 (program () (opt-prelude 1 0 1 2 #f)
464 (bind (x #f 0) (x1 #f 1)) (label _)
465 (lexical #t #f ref 1) (call return 1)
469 (assert-tree-il->glil
471 (lambda-case (((x) #f #f #f () (x1))
473 (lambda-case (((y) #f #f #f () (y1))
477 (program () (std-prelude 0 0 #f) (label _)
478 (program () (std-prelude 1 1 #f)
479 (bind (x #f 0)) (label _)
480 (program () (std-prelude 1 1 #f)
481 (bind (y #f 0)) (label _)
482 (lexical #f #f ref 0) (call return 1)
484 (lexical #t #f ref 0)
485 (call make-closure 1)
490 (with-test-prefix "sequence"
491 (assert-tree-il->glil
492 (begin (begin (const 2) (const #f)) (const #t))
493 (program () (std-prelude 0 0 #f) (label _)
494 (const #t) (call return 1)))
496 (assert-tree-il->glil
497 ;; This gets simplified by `peval'.
498 (primcall null? (begin (const #f) (const 2)))
499 (program () (std-prelude 0 0 #f) (label _)
500 (const #f) (call return 1))))
502 (with-test-prefix "values"
503 (assert-tree-il->glil
505 (primcall values (const 1) (const 2)))
506 (program () (std-prelude 0 0 #f) (label _)
507 (const 1) (call return 1)))
509 (assert-tree-il->glil
511 (primcall values (const 1) (const 2))
513 (program () (std-prelude 0 0 #f) (label _)
514 (const 1) (const 3) (call return/values 2)))
516 (assert-tree-il->glil
518 (primcall values (const 1) (const 2)))
519 (program () (std-prelude 0 0 #f) (label _)
520 (const 1) (call return 1)))
522 ;; Testing `(values foo)' in push context with RA.
523 (assert-tree-il->glil without-partial-evaluation
525 (letrec (lp) (#{lp ~V9KrhVD4PFEL6oCTrLg3A}#)
526 ((lambda ((name . lp))
527 (lambda-case ((() #f #f #f () ())
528 (primcall values (const (one two)))))))
529 (call (lexical lp #{lp ~V9KrhVD4PFEL6oCTrLg3A}#))))
530 (program () (std-prelude 0 0 #f) (label _)
531 (branch br _) ;; entering the fix, jump to :2
532 ;; :1 body of lp, jump to :3
533 (label _) (bind) (const (one two)) (branch br _) (unbind)
534 ;; :2 initial call of lp, jump to :1
535 (label _) (bind) (branch br _) (label _) (unbind)
536 ;; :3 the push continuation
537 (call cdr 1) (call return 1))))
539 ;; FIXME: binding info for or-hacked locals might bork the disassembler,
540 ;; and could be tightened in any case
541 (with-test-prefix "the or hack"
542 (assert-tree-il->glil without-partial-evaluation
543 (let (x) (y) ((const 1))
546 (let (a) (b) ((const 2))
548 (program () (std-prelude 0 1 #f) (label _)
549 (const 1) (bind (x #f 0)) (lexical #t #f set 0)
550 (lexical #t #f ref 0) (branch br-if-not ,l1)
551 (lexical #t #f ref 0) (call return 1)
553 (const 2) (bind (a #f 0)) (lexical #t #f set 0)
554 (lexical #t #f ref 0) (call return 1)
559 ;; second bound var is unreferenced
560 (assert-tree-il->glil without-partial-evaluation
561 (let (x) (y) ((const 1))
564 (let (a) (b) ((const 2))
566 (program () (std-prelude 0 1 #f) (label _)
567 (const 1) (bind (x #f 0)) (lexical #t #f set 0)
568 (lexical #t #f ref 0) (branch br-if-not ,l1)
569 (lexical #t #f ref 0) (call return 1)
571 (lexical #t #f ref 0) (call return 1)
575 (with-test-prefix "apply"
576 (assert-tree-il->glil
577 (primcall @apply (toplevel foo) (toplevel bar))
578 (program () (std-prelude 0 0 #f) (label _) (toplevel ref foo) (toplevel ref bar) (call tail-apply 2)))
579 (assert-tree-il->glil
580 (begin (primcall @apply (toplevel foo) (toplevel bar)) (void))
581 (program () (std-prelude 0 0 #f) (label _)
582 (call new-frame 0) (toplevel ref apply) (toplevel ref foo) (toplevel ref bar) (mv-call 2 ,l1)
583 (call drop 1) (branch br ,l2) (label ,l3) (mv-bind 0 #f)
585 (void) (call return 1))
586 (and (eq? l1 l3) (eq? l2 l4)))
587 (assert-tree-il->glil
588 (call (toplevel foo) (call (toplevel @apply) (toplevel bar) (toplevel baz)))
589 (program () (std-prelude 0 0 #f) (label _)
591 (call new-frame 0) (toplevel ref bar) (toplevel ref baz) (call apply 2)
592 (call tail-call 1))))
594 (with-test-prefix "call/cc"
595 (assert-tree-il->glil
596 (primcall @call-with-current-continuation (toplevel foo))
597 (program () (std-prelude 0 0 #f) (label _) (toplevel ref foo) (call tail-call/cc 1)))
598 (assert-tree-il->glil
599 (begin (primcall @call-with-current-continuation (toplevel foo)) (void))
600 (program () (std-prelude 0 0 #f) (label _)
601 (call new-frame 0) (toplevel ref call-with-current-continuation) (toplevel ref foo) (mv-call 1 ,l1)
602 (call drop 1) (branch br ,l2) (label ,l3) (mv-bind 0 #f)
604 (void) (call return 1))
605 (and (eq? l1 l3) (eq? l2 l4)))
606 (assert-tree-il->glil
608 (call (toplevel @call-with-current-continuation) (toplevel bar)))
609 (program () (std-prelude 0 0 #f) (label _)
611 (toplevel ref bar) (call call/cc 1)
612 (call tail-call 1))))
615 (with-test-prefix "labels allocation"
616 (pass-if "http://debbugs.gnu.org/9769"
617 ((compile '(lambda ()
618 (let ((fail (lambda () #f)))
619 (let ((test (lambda () (fail))))
622 ;; Prevent inlining. We're testing analyze.scm's
623 ;; labels allocator here, and inlining it will
624 ;; reduce the entire thing to #t.
625 #:opts '(#:partial-eval? #f)))))
628 (with-test-prefix "tree-il-fold"
630 (pass-if "empty tree"
631 (let ((leaf? #f) (up? #f) (down? #f) (mark (list 'mark)))
633 (tree-il-fold (lambda (x y) (set! leaf? #t) y)
634 (lambda (x y) (set! down? #t) y)
635 (lambda (x y) (set! up? #t) y)
642 (pass-if "lambda and application"
643 (let* ((leaves '()) (ups '()) (downs '())
644 (result (tree-il-fold (lambda (x y)
645 (set! leaves (cons x leaves))
648 (set! downs (cons x downs))
651 (set! ups (cons x ups))
657 (((x y) #f #f #f () (x1 y1))
662 (and (equal? (map strip-source leaves)
663 (list (make-lexical-ref #f 'y 'y1)
664 (make-lexical-ref #f 'x 'x1)
665 (make-toplevel-ref #f '+)))
667 (equal? (reverse (map strip-source ups))
668 (map strip-source downs))))))
675 ;; Make sure we get English messages.
676 (setlocale LC_ALL "C")
678 (define (call-with-warnings thunk)
679 (let ((port (open-output-string)))
680 (with-fluids ((*current-warning-port* port)
681 (*current-warning-prefix* ""))
683 (let ((warnings (get-output-string port)))
684 (string-tokenize warnings
685 (char-set-complement (char-set #\newline))))))
687 (define %opts-w-unused
688 '(#:warnings (unused-variable)))
690 (define %opts-w-unused-toplevel
691 '(#:warnings (unused-toplevel)))
693 (define %opts-w-unbound
694 '(#:warnings (unbound-variable)))
696 (define %opts-w-arity
697 '(#:warnings (arity-mismatch)))
699 (define %opts-w-format
700 '(#:warnings (format)))
703 (with-test-prefix "warnings"
705 (pass-if "unknown warning type"
706 (let ((w (call-with-warnings
708 (compile #t #:opts '(#:warnings (does-not-exist)))))))
709 (and (= (length w) 1)
710 (number? (string-contains (car w) "unknown warning")))))
712 (with-test-prefix "unused-variable"
715 (null? (call-with-warnings
717 (compile '(lambda (x y) (+ x y))
718 #:opts %opts-w-unused)))))
720 (pass-if "let/unused"
721 (let ((w (call-with-warnings
723 (compile '(lambda (x)
726 #:opts %opts-w-unused)))))
727 (and (= (length w) 1)
728 (number? (string-contains (car w) "unused variable `y'")))))
730 (pass-if "shadowed variable"
731 (let ((w (call-with-warnings
733 (compile '(lambda (x)
737 #:opts %opts-w-unused)))))
738 (and (= (length w) 1)
739 (number? (string-contains (car w) "unused variable `y'")))))
742 (null? (call-with-warnings
745 (letrec ((x (lambda () (y)))
748 #:opts %opts-w-unused)))))
750 (pass-if "unused argument"
751 ;; Unused arguments should not be reported.
752 (null? (call-with-warnings
754 (compile '(lambda (x y z) #t)
755 #:opts %opts-w-unused)))))
757 (pass-if "special variable names"
758 (null? (call-with-warnings
761 (let ((_ 'underscore)
762 (#{gensym name}# 'ignore-me))
765 #:opts %opts-w-unused))))))
767 (with-test-prefix "unused-toplevel"
769 (pass-if "used after definition"
770 (null? (call-with-warnings
772 (let ((in (open-input-string
773 "(define foo 2) foo")))
776 #:opts %opts-w-unused-toplevel))))))
778 (pass-if "used before definition"
779 (null? (call-with-warnings
781 (let ((in (open-input-string
782 "(define (bar) foo) (define foo 2) (bar)")))
785 #:opts %opts-w-unused-toplevel))))))
787 (pass-if "unused but public"
788 (let ((in (open-input-string
789 "(define-module (test-suite tree-il x) #:export (bar))
790 (define (bar) #t)")))
791 (null? (call-with-warnings
795 #:opts %opts-w-unused-toplevel))))))
797 (pass-if "unused but public (more)"
798 (let ((in (open-input-string
799 "(define-module (test-suite tree-il x) #:export (bar))
802 (define (foo) #t)")))
803 (null? (call-with-warnings
807 #:opts %opts-w-unused-toplevel))))))
809 (pass-if "unused but define-public"
810 (null? (call-with-warnings
812 (compile '(define-public foo 2)
814 #:opts %opts-w-unused-toplevel)))))
816 (pass-if "used by macro"
817 ;; FIXME: See comment about macros at `unused-toplevel-analysis'.
820 (null? (call-with-warnings
822 (let ((in (open-input-string
825 (syntax-rules () ((_) (bar))))")))
828 #:opts %opts-w-unused-toplevel))))))
831 (let ((w (call-with-warnings
833 (compile '(define foo 2)
835 #:opts %opts-w-unused-toplevel)))))
836 (and (= (length w) 1)
837 (number? (string-contains (car w)
838 (format #f "top-level variable `~A'"
841 (pass-if "unused recursive"
842 (let ((w (call-with-warnings
844 (compile '(define (foo) (foo))
846 #:opts %opts-w-unused-toplevel)))))
847 (and (= (length w) 1)
848 (number? (string-contains (car w)
849 (format #f "top-level variable `~A'"
852 (pass-if "unused mutually recursive"
853 (let* ((in (open-input-string
854 "(define (foo) (bar)) (define (bar) (foo))"))
855 (w (call-with-warnings
859 #:opts %opts-w-unused-toplevel)))))
860 (and (= (length w) 2)
861 (number? (string-contains (car w)
862 (format #f "top-level variable `~A'"
864 (number? (string-contains (cadr w)
865 (format #f "top-level variable `~A'"
868 (pass-if "special variable names"
869 (null? (call-with-warnings
871 (compile '(define #{gensym name}# 'ignore-me)
873 #:opts %opts-w-unused-toplevel))))))
875 (with-test-prefix "unbound variable"
878 (null? (call-with-warnings
880 (compile '+ #:opts %opts-w-unbound)))))
884 (w (call-with-warnings
888 #:opts %opts-w-unbound)))))
889 (and (= (length w) 1)
890 (number? (string-contains (car w)
891 (format #f "unbound variable `~A'"
896 (w (call-with-warnings
898 (compile `(set! ,v 7)
900 #:opts %opts-w-unbound)))))
901 (and (= (length w) 1)
902 (number? (string-contains (car w)
903 (format #f "unbound variable `~A'"
906 (pass-if "module-local top-level is visible"
907 (let ((m (make-module))
909 (beautify-user-module! m)
910 (compile `(define ,v 123)
911 #:env m #:opts %opts-w-unbound)
912 (null? (call-with-warnings
917 #:opts %opts-w-unbound))))))
919 (pass-if "module-local top-level is visible after"
920 (let ((m (make-module))
922 (beautify-user-module! m)
923 (null? (call-with-warnings
925 (let ((in (open-input-string
928 (define chbouib 5)")))
931 #:opts %opts-w-unbound)))))))
933 (pass-if "optional arguments are visible"
934 (null? (call-with-warnings
936 (compile '(lambda* (x #:optional y z) (list x y z))
937 #:opts %opts-w-unbound
940 (pass-if "keyword arguments are visible"
941 (null? (call-with-warnings
943 (compile '(lambda* (x #:key y z) (list x y z))
944 #:opts %opts-w-unbound
947 (pass-if "GOOPS definitions are visible"
948 (let ((m (make-module))
950 (beautify-user-module! m)
951 (module-use! m (resolve-interface '(oop goops)))
952 (null? (call-with-warnings
954 (let ((in (open-input-string
955 "(define-class <foo> ()
956 (bar #:getter foo-bar))
957 (define z (foo-bar (make <foo>)))")))
960 #:opts %opts-w-unbound))))))))
962 (with-test-prefix "arity mismatch"
965 (null? (call-with-warnings
967 (compile '(cons 'a 'b) #:opts %opts-w-arity)))))
969 (pass-if "direct application"
970 (let ((w (call-with-warnings
972 (compile '((lambda (x y) (or x y)) 1 2 3 4 5)
975 (and (= (length w) 1)
976 (number? (string-contains (car w)
977 "wrong number of arguments to")))))
979 (let ((w (call-with-warnings
981 (compile '(let ((f (lambda (x y) (+ x y))))
985 (and (= (length w) 1)
986 (number? (string-contains (car w)
987 "wrong number of arguments to")))))
990 (let ((w (call-with-warnings
992 (compile '(cons 1 2 3 4)
995 (and (= (length w) 1)
996 (number? (string-contains (car w)
997 "wrong number of arguments to")))))
999 (pass-if "alias to global"
1000 (let ((w (call-with-warnings
1002 (compile '(let ((f cons)) (f 1 2 3 4))
1003 #:opts %opts-w-arity
1005 (and (= (length w) 1)
1006 (number? (string-contains (car w)
1007 "wrong number of arguments to")))))
1009 (pass-if "alias to lexical to global"
1010 (let ((w (call-with-warnings
1012 (compile '(let ((f number?))
1015 #:opts %opts-w-arity
1017 (and (= (length w) 1)
1018 (number? (string-contains (car w)
1019 "wrong number of arguments to")))))
1021 (pass-if "alias to lexical"
1022 (let ((w (call-with-warnings
1024 (compile '(let ((f (lambda (x y z) (+ x y z))))
1027 #:opts %opts-w-arity
1029 (and (= (length w) 1)
1030 (number? (string-contains (car w)
1031 "wrong number of arguments to")))))
1034 (let ((w (call-with-warnings
1036 (compile '(letrec ((odd? (lambda (x) (even? (1- x))))
1041 #:opts %opts-w-arity
1043 (and (= (length w) 1)
1044 (number? (string-contains (car w)
1045 "wrong number of arguments to")))))
1047 (pass-if "case-lambda"
1048 (null? (call-with-warnings
1050 (compile '(let ((f (case-lambda
1057 #:opts %opts-w-arity
1060 (pass-if "case-lambda with wrong number of arguments"
1061 (let ((w (call-with-warnings
1063 (compile '(let ((f (case-lambda
1067 #:opts %opts-w-arity
1069 (and (= (length w) 1)
1070 (number? (string-contains (car w)
1071 "wrong number of arguments to")))))
1073 (pass-if "case-lambda*"
1074 (null? (call-with-warnings
1076 (compile '(let ((f (case-lambda*
1077 ((x #:optional y) 1)
1079 ((x y #:key z) 3))))
1084 #:opts %opts-w-arity
1087 (pass-if "case-lambda* with wrong arguments"
1088 (let ((w (call-with-warnings
1090 (compile '(let ((f (case-lambda*
1091 ((x #:optional y) 1)
1093 ((x y #:key z) 3))))
1096 #:opts %opts-w-arity
1098 (and (= (length w) 2)
1099 (null? (filter (lambda (w)
1103 w "wrong number of arguments to"))))
1106 (pass-if "local toplevel-defines"
1107 (let ((w (call-with-warnings
1109 (let ((in (open-input-string "
1110 (define (g x) (f x))
1112 (read-and-compile in
1113 #:opts %opts-w-arity
1114 #:to 'assembly))))))
1115 (and (= (length w) 1)
1116 (number? (string-contains (car w)
1117 "wrong number of arguments to")))))
1119 (pass-if "global toplevel alias"
1120 (let ((w (call-with-warnings
1122 (let ((in (open-input-string "
1124 (define (g) (f))")))
1125 (read-and-compile in
1126 #:opts %opts-w-arity
1127 #:to 'assembly))))))
1128 (and (= (length w) 1)
1129 (number? (string-contains (car w)
1130 "wrong number of arguments to")))))
1132 (pass-if "local toplevel overrides global"
1133 (null? (call-with-warnings
1135 (let ((in (open-input-string "
1137 (define (foo x) (cons))")))
1138 (read-and-compile in
1139 #:opts %opts-w-arity
1140 #:to 'assembly))))))
1142 (pass-if "keyword not passed and quiet"
1143 (null? (call-with-warnings
1145 (compile '(let ((f (lambda* (x #:key y) y)))
1147 #:opts %opts-w-arity
1150 (pass-if "keyword passed and quiet"
1151 (null? (call-with-warnings
1153 (compile '(let ((f (lambda* (x #:key y) y)))
1155 #:opts %opts-w-arity
1158 (pass-if "keyword passed to global and quiet"
1159 (null? (call-with-warnings
1161 (let ((in (open-input-string "
1162 (use-modules (system base compile))
1163 (compile '(+ 2 3) #:env (current-module))")))
1164 (read-and-compile in
1165 #:opts %opts-w-arity
1166 #:to 'assembly))))))
1168 (pass-if "extra keyword"
1169 (let ((w (call-with-warnings
1171 (compile '(let ((f (lambda* (x #:key y) y)))
1173 #:opts %opts-w-arity
1175 (and (= (length w) 1)
1176 (number? (string-contains (car w)
1177 "wrong number of arguments to")))))
1179 (pass-if "extra keywords allowed"
1180 (null? (call-with-warnings
1182 (compile '(let ((f (lambda* (x #:key y #:allow-other-keys)
1185 #:opts %opts-w-arity
1186 #:to 'assembly))))))
1188 (with-test-prefix "format"
1190 (pass-if "quiet (no args)"
1191 (null? (call-with-warnings
1193 (compile '(format #t "hey!")
1194 #:opts %opts-w-format
1197 (pass-if "quiet (1 arg)"
1198 (null? (call-with-warnings
1200 (compile '(format #t "hey ~A!" "you")
1201 #:opts %opts-w-format
1204 (pass-if "quiet (2 args)"
1205 (null? (call-with-warnings
1207 (compile '(format #t "~A ~A!" "hello" "world")
1208 #:opts %opts-w-format
1211 (pass-if "wrong port arg"
1212 (let ((w (call-with-warnings
1214 (compile '(format 10 "foo")
1215 #:opts %opts-w-format
1217 (and (= (length w) 1)
1218 (number? (string-contains (car w)
1219 "wrong port argument")))))
1221 (pass-if "non-literal format string"
1222 (let ((w (call-with-warnings
1224 (compile '(format #f fmt)
1225 #:opts %opts-w-format
1227 (and (= (length w) 1)
1228 (number? (string-contains (car w)
1229 "non-literal format string")))))
1231 (pass-if "non-literal format string using gettext"
1232 (null? (call-with-warnings
1234 (compile '(format #t (gettext "~A ~A!") "hello" "world")
1235 #:opts %opts-w-format
1238 (pass-if "non-literal format string using gettext as _"
1239 (null? (call-with-warnings
1241 (compile '(format #t (_ "~A ~A!") "hello" "world")
1242 #:opts %opts-w-format
1245 (pass-if "non-literal format string using ngettext"
1246 (null? (call-with-warnings
1248 (compile '(format #t
1249 (ngettext "~a thing" "~a things" n "dom") n)
1250 #:opts %opts-w-format
1253 (pass-if "non-literal format string using ngettext as N_"
1254 (null? (call-with-warnings
1256 (compile '(format #t (N_ "~a thing" "~a things" n) n)
1257 #:opts %opts-w-format
1260 (pass-if "non-literal format string with (define _ gettext)"
1261 (null? (call-with-warnings
1266 (format #t (_ "~A ~A!") "hello" "world")))
1267 #:opts %opts-w-format
1270 (pass-if "wrong format string"
1271 (let ((w (call-with-warnings
1273 (compile '(format #f 'not-a-string)
1274 #:opts %opts-w-format
1276 (and (= (length w) 1)
1277 (number? (string-contains (car w)
1278 "wrong format string")))))
1280 (pass-if "wrong number of args"
1281 (let ((w (call-with-warnings
1283 (compile '(format "shbweeb")
1284 #:opts %opts-w-format
1286 (and (= (length w) 1)
1287 (number? (string-contains (car w)
1288 "wrong number of arguments")))))
1290 (pass-if "~%, ~~, ~&, ~t, ~_, and ~\\n"
1291 (null? (call-with-warnings
1293 (compile '((@ (ice-9 format) format) some-port
1294 "~&~3_~~ ~\n~12they~%")
1295 #:opts %opts-w-format
1298 (pass-if "one missing argument"
1299 (let ((w (call-with-warnings
1301 (compile '(format some-port "foo ~A~%")
1302 #:opts %opts-w-format
1304 (and (= (length w) 1)
1305 (number? (string-contains (car w)
1306 "expected 1, got 0")))))
1308 (pass-if "one missing argument, gettext"
1309 (let ((w (call-with-warnings
1311 (compile '(format some-port (gettext "foo ~A~%"))
1312 #:opts %opts-w-format
1314 (and (= (length w) 1)
1315 (number? (string-contains (car w)
1316 "expected 1, got 0")))))
1318 (pass-if "two missing arguments"
1319 (let ((w (call-with-warnings
1321 (compile '((@ (ice-9 format) format) #f
1322 "foo ~10,2f and bar ~S~%")
1323 #:opts %opts-w-format
1325 (and (= (length w) 1)
1326 (number? (string-contains (car w)
1327 "expected 2, got 0")))))
1329 (pass-if "one given, one missing argument"
1330 (let ((w (call-with-warnings
1332 (compile '(format #t "foo ~A and ~S~%" hey)
1333 #:opts %opts-w-format
1335 (and (= (length w) 1)
1336 (number? (string-contains (car w)
1337 "expected 2, got 1")))))
1339 (pass-if "too many arguments"
1340 (let ((w (call-with-warnings
1342 (compile '(format #t "foo ~A~%" 1 2)
1343 #:opts %opts-w-format
1345 (and (= (length w) 1)
1346 (number? (string-contains (car w)
1347 "expected 1, got 2")))))
1350 (null? (call-with-warnings
1352 (compile '((@ (ice-9 format) format) #t
1353 "foo ~h ~a~%" 123.4 'bar)
1354 #:opts %opts-w-format
1357 (pass-if "~:h with locale object"
1358 (null? (call-with-warnings
1360 (compile '((@ (ice-9 format) format) #t
1361 "foo ~:h~%" 123.4 %global-locale)
1362 #:opts %opts-w-format
1365 (pass-if "~:h without locale object"
1366 (let ((w (call-with-warnings
1368 (compile '((@ (ice-9 format) format) #t "foo ~,2:h" 123.4)
1369 #:opts %opts-w-format
1371 (and (= (length w) 1)
1372 (number? (string-contains (car w)
1373 "expected 2, got 1")))))
1375 (with-test-prefix "conditionals"
1377 (null? (call-with-warnings
1379 (compile '((@ (ice-9 format) format) #f "~A ~[foo~;bar~;baz~;~] ~10,2f"
1381 #:opts %opts-w-format
1384 (pass-if "literals with selector"
1385 (let ((w (call-with-warnings
1387 (compile '((@ (ice-9 format) format) #f "~2[foo~;bar~;baz~;~] ~A"
1389 #:opts %opts-w-format
1391 (and (= (length w) 1)
1392 (number? (string-contains (car w)
1393 "expected 1, got 2")))))
1395 (pass-if "escapes (exact count)"
1396 (let ((w (call-with-warnings
1398 (compile '((@ (ice-9 format) format) #f "~[~a~;~a~]")
1399 #:opts %opts-w-format
1401 (and (= (length w) 1)
1402 (number? (string-contains (car w)
1403 "expected 2, got 0")))))
1405 (pass-if "escapes with selector"
1406 (let ((w (call-with-warnings
1408 (compile '((@ (ice-9 format) format) #f "~1[chbouib~;~a~]")
1409 #:opts %opts-w-format
1411 (and (= (length w) 1)
1412 (number? (string-contains (car w)
1413 "expected 1, got 0")))))
1415 (pass-if "escapes, range"
1416 (let ((w (call-with-warnings
1418 (compile '((@ (ice-9 format) format) #f "~[chbouib~;~a~;~2*~a~]")
1419 #:opts %opts-w-format
1421 (and (= (length w) 1)
1422 (number? (string-contains (car w)
1423 "expected 1 to 4, got 0")))))
1426 (let ((w (call-with-warnings
1428 (compile '((@ (ice-9 format) format) #f "~@[temperature=~d~]")
1429 #:opts %opts-w-format
1431 (and (= (length w) 1)
1432 (number? (string-contains (car w)
1433 "expected 1, got 0")))))
1436 (let ((w (call-with-warnings
1438 (compile '((@ (ice-9 format) format) #f "~:[~[hey~;~a~;~va~]~;~3*~]")
1439 #:opts %opts-w-format
1441 (and (= (length w) 1)
1442 (number? (string-contains (car w)
1443 "expected 2 to 4, got 0")))))
1445 (pass-if "unterminated"
1446 (let ((w (call-with-warnings
1448 (compile '((@ (ice-9 format) format) #f "~[unterminated")
1449 #:opts %opts-w-format
1451 (and (= (length w) 1)
1452 (number? (string-contains (car w)
1453 "unterminated conditional")))))
1455 (pass-if "unexpected ~;"
1456 (let ((w (call-with-warnings
1458 (compile '((@ (ice-9 format) format) #f "foo~;bar")
1459 #:opts %opts-w-format
1461 (and (= (length w) 1)
1462 (number? (string-contains (car w)
1465 (pass-if "unexpected ~]"
1466 (let ((w (call-with-warnings
1468 (compile '((@ (ice-9 format) format) #f "foo~]")
1469 #:opts %opts-w-format
1471 (and (= (length w) 1)
1472 (number? (string-contains (car w)
1476 (null? (call-with-warnings
1478 (compile '((@ (ice-9 format) format) #f "~A ~{~S~} ~A"
1479 'hello '("ladies" "and")
1481 #:opts %opts-w-format
1484 (pass-if "~{...~}, too many args"
1485 (let ((w (call-with-warnings
1487 (compile '((@ (ice-9 format) format) #f "~{~S~}" 1 2 3)
1488 #:opts %opts-w-format
1490 (and (= (length w) 1)
1491 (number? (string-contains (car w)
1492 "expected 1, got 3")))))
1495 (null? (call-with-warnings
1497 (compile '((@ (ice-9 format) format) #f "~@{~S~}" 1 2 3)
1498 #:opts %opts-w-format
1501 (pass-if "~@{...~}, too few args"
1502 (let ((w (call-with-warnings
1504 (compile '((@ (ice-9 format) format) #f "~A ~@{~S~}")
1505 #:opts %opts-w-format
1507 (and (= (length w) 1)
1508 (number? (string-contains (car w)
1509 "expected at least 1, got 0")))))
1511 (pass-if "unterminated ~{...~}"
1512 (let ((w (call-with-warnings
1514 (compile '((@ (ice-9 format) format) #f "~{")
1515 #:opts %opts-w-format
1517 (and (= (length w) 1)
1518 (number? (string-contains (car w)
1522 (null? (call-with-warnings
1524 (compile '((@ (ice-9 format) format) #f "~:@(~A ~A~)" 'foo 'bar)
1525 #:opts %opts-w-format
1529 (let ((w (call-with-warnings
1531 (compile '((@ (ice-9 format) format) #f "~v_foo")
1532 #:opts %opts-w-format
1534 (and (= (length w) 1)
1535 (number? (string-contains (car w)
1536 "expected 1, got 0")))))
1538 (null? (call-with-warnings
1540 (compile '((@ (ice-9 format) format) #f "~v:@y" 1 123)
1541 #:opts %opts-w-format
1546 (let ((w (call-with-warnings
1548 (compile '((@ (ice-9 format) format) #f "~2*~a" 'a 'b)
1549 #:opts %opts-w-format
1551 (and (= (length w) 1)
1552 (number? (string-contains (car w)
1553 "expected 3, got 2")))))
1556 (null? (call-with-warnings
1558 (compile '((@ (ice-9 format) format) #f "~?" "~d ~d" '(1 2))
1559 #:opts %opts-w-format
1562 (pass-if "complex 1"
1563 (let ((w (call-with-warnings
1565 (compile '((@ (ice-9 format) format) #f
1566 "~4@S ~32S~@[;; ~1{~@?~}~]~@[~61t at ~a~]\n"
1568 #:opts %opts-w-format
1570 (and (= (length w) 1)
1571 (number? (string-contains (car w)
1572 "expected 4, got 6")))))
1574 (pass-if "complex 2"
1575 (let ((w (call-with-warnings
1577 (compile '((@ (ice-9 format) format) #f
1578 "~:(~A~) Commands~:[~; [abbrev]~]:~2%"
1580 #:opts %opts-w-format
1582 (and (= (length w) 1)
1583 (number? (string-contains (car w)
1584 "expected 2, got 4")))))
1586 (pass-if "complex 3"
1587 (let ((w (call-with-warnings
1589 (compile '((@ (ice-9 format) format) #f "~9@a~:[~*~3_~;~3d~] ~v:@y~%")
1590 #:opts %opts-w-format
1592 (and (= (length w) 1)
1593 (number? (string-contains (car w)
1594 "expected 5, got 0")))))
1596 (pass-if "ice-9 format"
1597 (let ((w (call-with-warnings
1599 (let ((in (open-input-string
1600 "(use-modules ((ice-9 format)
1601 #:renamer (symbol-prefix-proc 'i9-)))
1602 (i9-format #t \"yo! ~A\" 1 2)")))
1603 (read-and-compile in
1604 #:opts %opts-w-format
1605 #:to 'assembly))))))
1606 (and (= (length w) 1)
1607 (number? (string-contains (car w)
1608 "expected 1, got 2")))))
1610 (pass-if "not format"
1611 (null? (call-with-warnings
1613 (compile '(let ((format chbouib))
1614 (format #t "not ~A a format string"))
1615 #:opts %opts-w-format
1618 (with-test-prefix "simple-format"
1621 (null? (call-with-warnings
1623 (compile '(simple-format #t "foo ~a bar ~s ~%~~" 1 2)
1624 #:opts %opts-w-format
1627 (pass-if "wrong number of args"
1628 (let ((w (call-with-warnings
1630 (compile '(simple-format #t "foo ~a ~s~%" 'one-missing)
1631 #:opts %opts-w-format
1633 (and (= (length w) 1)
1634 (number? (string-contains (car w) "wrong number")))))
1636 (pass-if "unsupported"
1637 (let ((w (call-with-warnings
1639 (compile '(simple-format #t "foo ~x~%" 16)
1640 #:opts %opts-w-format
1642 (and (= (length w) 1)
1643 (number? (string-contains (car w) "unsupported format option")))))
1645 (pass-if "unsupported, gettext"
1646 (let ((w (call-with-warnings
1648 (compile '(simple-format #t (gettext "foo ~2f~%") 3.14)
1649 #:opts %opts-w-format
1651 (and (= (length w) 1)
1652 (number? (string-contains (car w) "unsupported format option")))))
1654 (pass-if "unsupported, ngettext"
1655 (let ((w (call-with-warnings
1657 (compile '(simple-format #t (ngettext "s ~x" "p ~x" x) x)
1658 #:opts %opts-w-format
1660 (and (= (length w) 1)
1661 (number? (string-contains (car w) "unsupported format option"))))))))