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 (apply (primitive +) (void) (const 1))
88 (program () (std-prelude 0 0 #f) (label _) (void) (call add1 1) (call return 1))))
90 (with-test-prefix "application"
92 (apply (toplevel foo) (const 1))
93 (program () (std-prelude 0 0 #f) (label _) (toplevel ref foo) (const 1) (call tail-call 1)))
95 (begin (apply (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 (apply (toplevel foo) (apply (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 (apply (primitive 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 (apply (primitive 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 with-options (#:partial-eval? #f #:cse? #f)
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)) (apply (primitive 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) (apply (primitive 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) (apply (primitive 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))
188 (apply (primitive null?)
189 (set! (lexical x y) (apply (primitive 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 (apply (primitive 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 (apply (primitive 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 (apply (primitive 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 (apply (primitive 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 (apply (primitive 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 (apply (primitive 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 (apply (primitive 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 (apply (primitive 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 (apply (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) ((apply (toplevel foo)) (apply (toplevel bar)))
361 (apply (primitive +) (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) ((apply (toplevel foo)) (apply (toplevel bar)))
379 (apply (primitive +) (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 (apply (primitive 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
504 (apply (primitive values)
505 (apply (primitive values) (const 1) (const 2)))
506 (program () (std-prelude 0 0 #f) (label _)
507 (const 1) (call return 1)))
509 (assert-tree-il->glil
510 (apply (primitive values)
511 (apply (primitive 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 (apply (primitive 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
524 (apply (primitive cdr)
525 (letrec (lp) (#{lp ~V9KrhVD4PFEL6oCTrLg3A}#)
526 ((lambda ((name . lp))
527 (lambda-case ((() #f #f #f () ())
528 (apply (toplevel values) (const (one two)))))))
529 (apply (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 (apply (primitive @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 (apply (primitive @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 (apply (toplevel foo) (apply (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 (apply (primitive @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 (apply (primitive @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
607 (apply (toplevel foo)
608 (apply (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 "top-level applicable struct"
1107 (null? (call-with-warnings
1109 (compile '(let ((p current-warning-port))
1112 #:opts %opts-w-arity
1115 (pass-if "top-level applicable struct with wrong arguments"
1116 (let ((w (call-with-warnings
1118 (compile '(let ((p current-warning-port))
1120 #:opts %opts-w-arity
1122 (and (= (length w) 1)
1123 (number? (string-contains (car w)
1124 "wrong number of arguments to")))))
1126 (pass-if "local toplevel-defines"
1127 (let ((w (call-with-warnings
1129 (let ((in (open-input-string "
1130 (define (g x) (f x))
1132 (read-and-compile in
1133 #:opts %opts-w-arity
1134 #:to 'assembly))))))
1135 (and (= (length w) 1)
1136 (number? (string-contains (car w)
1137 "wrong number of arguments to")))))
1139 (pass-if "global toplevel alias"
1140 (let ((w (call-with-warnings
1142 (let ((in (open-input-string "
1144 (define (g) (f))")))
1145 (read-and-compile in
1146 #:opts %opts-w-arity
1147 #:to 'assembly))))))
1148 (and (= (length w) 1)
1149 (number? (string-contains (car w)
1150 "wrong number of arguments to")))))
1152 (pass-if "local toplevel overrides global"
1153 (null? (call-with-warnings
1155 (let ((in (open-input-string "
1157 (define (foo x) (cons))")))
1158 (read-and-compile in
1159 #:opts %opts-w-arity
1160 #:to 'assembly))))))
1162 (pass-if "keyword not passed and quiet"
1163 (null? (call-with-warnings
1165 (compile '(let ((f (lambda* (x #:key y) y)))
1167 #:opts %opts-w-arity
1170 (pass-if "keyword passed and quiet"
1171 (null? (call-with-warnings
1173 (compile '(let ((f (lambda* (x #:key y) y)))
1175 #:opts %opts-w-arity
1178 (pass-if "keyword passed to global and quiet"
1179 (null? (call-with-warnings
1181 (let ((in (open-input-string "
1182 (use-modules (system base compile))
1183 (compile '(+ 2 3) #:env (current-module))")))
1184 (read-and-compile in
1185 #:opts %opts-w-arity
1186 #:to 'assembly))))))
1188 (pass-if "extra keyword"
1189 (let ((w (call-with-warnings
1191 (compile '(let ((f (lambda* (x #:key y) y)))
1193 #:opts %opts-w-arity
1195 (and (= (length w) 1)
1196 (number? (string-contains (car w)
1197 "wrong number of arguments to")))))
1199 (pass-if "extra keywords allowed"
1200 (null? (call-with-warnings
1202 (compile '(let ((f (lambda* (x #:key y #:allow-other-keys)
1205 #:opts %opts-w-arity
1206 #:to 'assembly))))))
1208 (with-test-prefix "format"
1210 (pass-if "quiet (no args)"
1211 (null? (call-with-warnings
1213 (compile '(format #t "hey!")
1214 #:opts %opts-w-format
1217 (pass-if "quiet (1 arg)"
1218 (null? (call-with-warnings
1220 (compile '(format #t "hey ~A!" "you")
1221 #:opts %opts-w-format
1224 (pass-if "quiet (2 args)"
1225 (null? (call-with-warnings
1227 (compile '(format #t "~A ~A!" "hello" "world")
1228 #:opts %opts-w-format
1231 (pass-if "wrong port arg"
1232 (let ((w (call-with-warnings
1234 (compile '(format 10 "foo")
1235 #:opts %opts-w-format
1237 (and (= (length w) 1)
1238 (number? (string-contains (car w)
1239 "wrong port argument")))))
1241 (pass-if "non-literal format string"
1242 (let ((w (call-with-warnings
1244 (compile '(format #f fmt)
1245 #:opts %opts-w-format
1247 (and (= (length w) 1)
1248 (number? (string-contains (car w)
1249 "non-literal format string")))))
1251 (pass-if "non-literal format string using gettext"
1252 (null? (call-with-warnings
1254 (compile '(format #t (gettext "~A ~A!") "hello" "world")
1255 #:opts %opts-w-format
1258 (pass-if "non-literal format string using gettext as _"
1259 (null? (call-with-warnings
1261 (compile '(format #t (_ "~A ~A!") "hello" "world")
1262 #:opts %opts-w-format
1265 (pass-if "non-literal format string using gettext as module-ref _"
1266 (null? (call-with-warnings
1268 (compile '(format #t ((@@ (foo) _) "~A ~A!") "hello" "world")
1269 #:opts %opts-w-format
1272 (pass-if "non-literal format string using gettext as lexical _"
1273 (null? (call-with-warnings
1275 (compile '(let ((_ (lambda (s)
1276 (gettext s "my-domain"))))
1277 (format #t (_ "~A ~A!") "hello" "world"))
1278 #:opts %opts-w-format
1281 (pass-if "non-literal format string using ngettext"
1282 (null? (call-with-warnings
1284 (compile '(format #t
1285 (ngettext "~a thing" "~a things" n "dom") n)
1286 #:opts %opts-w-format
1289 (pass-if "non-literal format string using ngettext as N_"
1290 (null? (call-with-warnings
1292 (compile '(format #t (N_ "~a thing" "~a things" n) n)
1293 #:opts %opts-w-format
1296 (pass-if "non-literal format string with (define _ gettext)"
1297 (null? (call-with-warnings
1302 (format #t (_ "~A ~A!") "hello" "world")))
1303 #:opts %opts-w-format
1306 (pass-if "wrong format string"
1307 (let ((w (call-with-warnings
1309 (compile '(format #f 'not-a-string)
1310 #:opts %opts-w-format
1312 (and (= (length w) 1)
1313 (number? (string-contains (car w)
1314 "wrong format string")))))
1316 (pass-if "wrong number of args"
1317 (let ((w (call-with-warnings
1319 (compile '(format "shbweeb")
1320 #:opts %opts-w-format
1322 (and (= (length w) 1)
1323 (number? (string-contains (car w)
1324 "wrong number of arguments")))))
1326 (pass-if "~%, ~~, ~&, ~t, ~_, and ~\\n"
1327 (null? (call-with-warnings
1329 (compile '((@ (ice-9 format) format) some-port
1330 "~&~3_~~ ~\n~12they~%")
1331 #:opts %opts-w-format
1334 (pass-if "one missing argument"
1335 (let ((w (call-with-warnings
1337 (compile '(format some-port "foo ~A~%")
1338 #:opts %opts-w-format
1340 (and (= (length w) 1)
1341 (number? (string-contains (car w)
1342 "expected 1, got 0")))))
1344 (pass-if "one missing argument, gettext"
1345 (let ((w (call-with-warnings
1347 (compile '(format some-port (gettext "foo ~A~%"))
1348 #:opts %opts-w-format
1350 (and (= (length w) 1)
1351 (number? (string-contains (car w)
1352 "expected 1, got 0")))))
1354 (pass-if "two missing arguments"
1355 (let ((w (call-with-warnings
1357 (compile '((@ (ice-9 format) format) #f
1358 "foo ~10,2f and bar ~S~%")
1359 #:opts %opts-w-format
1361 (and (= (length w) 1)
1362 (number? (string-contains (car w)
1363 "expected 2, got 0")))))
1365 (pass-if "one given, one missing argument"
1366 (let ((w (call-with-warnings
1368 (compile '(format #t "foo ~A and ~S~%" hey)
1369 #:opts %opts-w-format
1371 (and (= (length w) 1)
1372 (number? (string-contains (car w)
1373 "expected 2, got 1")))))
1375 (pass-if "too many arguments"
1376 (let ((w (call-with-warnings
1378 (compile '(format #t "foo ~A~%" 1 2)
1379 #:opts %opts-w-format
1381 (and (= (length w) 1)
1382 (number? (string-contains (car w)
1383 "expected 1, got 2")))))
1386 (null? (call-with-warnings
1388 (compile '((@ (ice-9 format) format) #t
1389 "foo ~h ~a~%" 123.4 'bar)
1390 #:opts %opts-w-format
1393 (pass-if "~:h with locale object"
1394 (null? (call-with-warnings
1396 (compile '((@ (ice-9 format) format) #t
1397 "foo ~:h~%" 123.4 %global-locale)
1398 #:opts %opts-w-format
1401 (pass-if "~:h without locale object"
1402 (let ((w (call-with-warnings
1404 (compile '((@ (ice-9 format) format) #t "foo ~,2:h" 123.4)
1405 #:opts %opts-w-format
1407 (and (= (length w) 1)
1408 (number? (string-contains (car w)
1409 "expected 2, got 1")))))
1411 (with-test-prefix "conditionals"
1413 (null? (call-with-warnings
1415 (compile '((@ (ice-9 format) format) #f "~A ~[foo~;bar~;baz~;~] ~10,2f"
1417 #:opts %opts-w-format
1420 (pass-if "literals with selector"
1421 (let ((w (call-with-warnings
1423 (compile '((@ (ice-9 format) format) #f "~2[foo~;bar~;baz~;~] ~A"
1425 #:opts %opts-w-format
1427 (and (= (length w) 1)
1428 (number? (string-contains (car w)
1429 "expected 1, got 2")))))
1431 (pass-if "escapes (exact count)"
1432 (let ((w (call-with-warnings
1434 (compile '((@ (ice-9 format) format) #f "~[~a~;~a~]")
1435 #:opts %opts-w-format
1437 (and (= (length w) 1)
1438 (number? (string-contains (car w)
1439 "expected 2, got 0")))))
1441 (pass-if "escapes with selector"
1442 (let ((w (call-with-warnings
1444 (compile '((@ (ice-9 format) format) #f "~1[chbouib~;~a~]")
1445 #:opts %opts-w-format
1447 (and (= (length w) 1)
1448 (number? (string-contains (car w)
1449 "expected 1, got 0")))))
1451 (pass-if "escapes, range"
1452 (let ((w (call-with-warnings
1454 (compile '((@ (ice-9 format) format) #f "~[chbouib~;~a~;~2*~a~]")
1455 #:opts %opts-w-format
1457 (and (= (length w) 1)
1458 (number? (string-contains (car w)
1459 "expected 1 to 4, got 0")))))
1462 (let ((w (call-with-warnings
1464 (compile '((@ (ice-9 format) format) #f "~@[temperature=~d~]")
1465 #:opts %opts-w-format
1467 (and (= (length w) 1)
1468 (number? (string-contains (car w)
1469 "expected 1, got 0")))))
1472 (let ((w (call-with-warnings
1474 (compile '((@ (ice-9 format) format) #f "~:[~[hey~;~a~;~va~]~;~3*~]")
1475 #:opts %opts-w-format
1477 (and (= (length w) 1)
1478 (number? (string-contains (car w)
1479 "expected 2 to 4, got 0")))))
1481 (pass-if "unterminated"
1482 (let ((w (call-with-warnings
1484 (compile '((@ (ice-9 format) format) #f "~[unterminated")
1485 #:opts %opts-w-format
1487 (and (= (length w) 1)
1488 (number? (string-contains (car w)
1489 "unterminated conditional")))))
1491 (pass-if "unexpected ~;"
1492 (let ((w (call-with-warnings
1494 (compile '((@ (ice-9 format) format) #f "foo~;bar")
1495 #:opts %opts-w-format
1497 (and (= (length w) 1)
1498 (number? (string-contains (car w)
1501 (pass-if "unexpected ~]"
1502 (let ((w (call-with-warnings
1504 (compile '((@ (ice-9 format) format) #f "foo~]")
1505 #:opts %opts-w-format
1507 (and (= (length w) 1)
1508 (number? (string-contains (car w)
1512 (null? (call-with-warnings
1514 (compile '((@ (ice-9 format) format) #f "~A ~{~S~} ~A"
1515 'hello '("ladies" "and")
1517 #:opts %opts-w-format
1520 (pass-if "~{...~}, too many args"
1521 (let ((w (call-with-warnings
1523 (compile '((@ (ice-9 format) format) #f "~{~S~}" 1 2 3)
1524 #:opts %opts-w-format
1526 (and (= (length w) 1)
1527 (number? (string-contains (car w)
1528 "expected 1, got 3")))))
1531 (null? (call-with-warnings
1533 (compile '((@ (ice-9 format) format) #f "~@{~S~}" 1 2 3)
1534 #:opts %opts-w-format
1537 (pass-if "~@{...~}, too few args"
1538 (let ((w (call-with-warnings
1540 (compile '((@ (ice-9 format) format) #f "~A ~@{~S~}")
1541 #:opts %opts-w-format
1543 (and (= (length w) 1)
1544 (number? (string-contains (car w)
1545 "expected at least 1, got 0")))))
1547 (pass-if "unterminated ~{...~}"
1548 (let ((w (call-with-warnings
1550 (compile '((@ (ice-9 format) format) #f "~{")
1551 #:opts %opts-w-format
1553 (and (= (length w) 1)
1554 (number? (string-contains (car w)
1558 (null? (call-with-warnings
1560 (compile '((@ (ice-9 format) format) #f "~:@(~A ~A~)" 'foo 'bar)
1561 #:opts %opts-w-format
1565 (let ((w (call-with-warnings
1567 (compile '((@ (ice-9 format) format) #f "~v_foo")
1568 #:opts %opts-w-format
1570 (and (= (length w) 1)
1571 (number? (string-contains (car w)
1572 "expected 1, got 0")))))
1574 (null? (call-with-warnings
1576 (compile '((@ (ice-9 format) format) #f "~v:@y" 1 123)
1577 #:opts %opts-w-format
1582 (let ((w (call-with-warnings
1584 (compile '((@ (ice-9 format) format) #f "~2*~a" 'a 'b)
1585 #:opts %opts-w-format
1587 (and (= (length w) 1)
1588 (number? (string-contains (car w)
1589 "expected 3, got 2")))))
1592 (null? (call-with-warnings
1594 (compile '((@ (ice-9 format) format) #f "~?" "~d ~d" '(1 2))
1595 #:opts %opts-w-format
1598 (pass-if "complex 1"
1599 (let ((w (call-with-warnings
1601 (compile '((@ (ice-9 format) format) #f
1602 "~4@S ~32S~@[;; ~1{~@?~}~]~@[~61t at ~a~]\n"
1604 #:opts %opts-w-format
1606 (and (= (length w) 1)
1607 (number? (string-contains (car w)
1608 "expected 4, got 6")))))
1610 (pass-if "complex 2"
1611 (let ((w (call-with-warnings
1613 (compile '((@ (ice-9 format) format) #f
1614 "~:(~A~) Commands~:[~; [abbrev]~]:~2%"
1616 #:opts %opts-w-format
1618 (and (= (length w) 1)
1619 (number? (string-contains (car w)
1620 "expected 2, got 4")))))
1622 (pass-if "complex 3"
1623 (let ((w (call-with-warnings
1625 (compile '((@ (ice-9 format) format) #f "~9@a~:[~*~3_~;~3d~] ~v:@y~%")
1626 #:opts %opts-w-format
1628 (and (= (length w) 1)
1629 (number? (string-contains (car w)
1630 "expected 5, got 0")))))
1632 (pass-if "ice-9 format"
1633 (let ((w (call-with-warnings
1635 (let ((in (open-input-string
1636 "(use-modules ((ice-9 format)
1637 #:renamer (symbol-prefix-proc 'i9-)))
1638 (i9-format #t \"yo! ~A\" 1 2)")))
1639 (read-and-compile in
1640 #:opts %opts-w-format
1641 #:to 'assembly))))))
1642 (and (= (length w) 1)
1643 (number? (string-contains (car w)
1644 "expected 1, got 2")))))
1646 (pass-if "not format"
1647 (null? (call-with-warnings
1649 (compile '(let ((format chbouib))
1650 (format #t "not ~A a format string"))
1651 #:opts %opts-w-format
1654 (with-test-prefix "simple-format"
1657 (null? (call-with-warnings
1659 (compile '(simple-format #t "foo ~a bar ~s ~%~~" 1 2)
1660 #:opts %opts-w-format
1663 (pass-if "wrong number of args"
1664 (let ((w (call-with-warnings
1666 (compile '(simple-format #t "foo ~a ~s~%" 'one-missing)
1667 #:opts %opts-w-format
1669 (and (= (length w) 1)
1670 (number? (string-contains (car w) "wrong number")))))
1672 (pass-if "unsupported"
1673 (let ((w (call-with-warnings
1675 (compile '(simple-format #t "foo ~x~%" 16)
1676 #:opts %opts-w-format
1678 (and (= (length w) 1)
1679 (number? (string-contains (car w) "unsupported format option")))))
1681 (pass-if "unsupported, gettext"
1682 (let ((w (call-with-warnings
1684 (compile '(simple-format #t (gettext "foo ~2f~%") 3.14)
1685 #:opts %opts-w-format
1687 (and (= (length w) 1)
1688 (number? (string-contains (car w) "unsupported format option")))))
1690 (pass-if "unsupported, ngettext"
1691 (let ((w (call-with-warnings
1693 (compile '(simple-format #t (ngettext "s ~x" "p ~x" x) x)
1694 #:opts %opts-w-format
1696 (and (= (length w) 1)
1697 (number? (string-contains (car w) "unsupported format option"))))))))