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 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 glil)
27 #:use-module (srfi srfi-13))
29 ;; Of course, the GLIL that is emitted depends on the source info of the
30 ;; input. Here we're not concerned about that, so we strip source
31 ;; information from the incoming tree-il.
33 (define (strip-source x)
34 (post-order! (lambda (x) (set! (tree-il-src x) #f))
37 (define-syntax assert-scheme->glil
40 (let ((tree-il (strip-source
41 (compile 'in #:from 'scheme #:to 'tree-il))))
43 (equal? (unparse-glil (compile tree-il #:from 'tree-il #:to 'glil))
46 (define-syntax assert-tree-il->glil
51 (let ((glil (unparse-glil
52 (compile (strip-source (parse-tree-il exp))
53 #:from 'tree-il #:to 'glil))))
55 (pat (guard test ...) #t)
58 (with-test-prefix "void"
61 (program () (std-prelude 0 0 #f) (label _) (void) (call return 1)))
63 (begin (void) (const 1))
64 (program () (std-prelude 0 0 #f) (label _) (const 1) (call return 1)))
66 (primcall + (void) (const 1))
67 (program () (std-prelude 0 0 #f) (label _) (void) (call add1 1) (call return 1))))
69 (with-test-prefix "application"
71 (call (toplevel foo) (const 1))
72 (program () (std-prelude 0 0 #f) (label _) (toplevel ref foo) (const 1) (call tail-call 1)))
74 (begin (call (toplevel foo) (const 1)) (void))
75 (program () (std-prelude 0 0 #f) (label _) (call new-frame 0) (toplevel ref foo) (const 1) (mv-call 1 ,l1)
76 (call drop 1) (branch br ,l2)
77 (label ,l3) (mv-bind 0 #f)
79 (void) (call return 1))
80 (and (eq? l1 l3) (eq? l2 l4)))
82 (call (toplevel foo) (call (toplevel bar)))
83 (program () (std-prelude 0 0 #f) (label _) (toplevel ref foo) (call new-frame 0) (toplevel ref bar) (call call 0)
86 (with-test-prefix "conditional"
88 (if (toplevel foo) (const 1) (const 2))
89 (program () (std-prelude 0 0 #f) (label _) (toplevel ref foo) (branch br-if-not ,l1)
90 (const 1) (call return 1)
91 (label ,l2) (const 2) (call return 1))
95 (begin (if (toplevel foo) (const 1) (const 2)) (const #f))
96 (program () (std-prelude 0 0 #f) (label _) (toplevel ref foo) (branch br-if-not ,l1) (branch br ,l2)
97 (label ,l3) (label ,l4) (const #f) (call return 1))
98 (eq? l1 l3) (eq? l2 l4))
100 (assert-tree-il->glil
101 (primcall null? (if (toplevel foo) (const 1) (const 2)))
102 (program () (std-prelude 0 0 #f) (label _) (toplevel ref foo) (branch br-if-not ,l1)
103 (const 1) (branch br ,l2)
104 (label ,l3) (const 2) (label ,l4)
105 (call null? 1) (call return 1))
106 (eq? l1 l3) (eq? l2 l4)))
108 (with-test-prefix "primitive-ref"
109 (assert-tree-il->glil
111 (program () (std-prelude 0 0 #f) (label _) (toplevel ref +) (call return 1)))
113 (assert-tree-il->glil
114 (begin (primitive +) (const #f))
115 (program () (std-prelude 0 0 #f) (label _) (const #f) (call return 1)))
117 (assert-tree-il->glil
118 (primcall null? (primitive +))
119 (program () (std-prelude 0 0 #f) (label _) (toplevel ref +) (call null? 1)
122 (with-test-prefix "lexical refs"
123 (assert-tree-il->glil
124 (let (x) (y) ((const 1)) (lexical x y))
125 (program () (std-prelude 0 1 #f) (label _)
126 (const 1) (bind (x #f 0)) (lexical #t #f set 0)
127 (lexical #t #f ref 0) (call return 1)
130 (assert-tree-il->glil
131 (let (x) (y) ((const 1)) (begin (lexical x y) (const #f)))
132 (program () (std-prelude 0 1 #f) (label _)
133 (const 1) (bind (x #f 0)) (lexical #t #f set 0)
134 (const #f) (call return 1)
137 (assert-tree-il->glil
138 (let (x) (y) ((const 1)) (primcall null? (lexical x y)))
139 (program () (std-prelude 0 1 #f) (label _)
140 (const 1) (bind (x #f 0)) (lexical #t #f set 0)
141 (lexical #t #f ref 0) (call null? 1) (call return 1)
144 (with-test-prefix "lexical sets"
145 (assert-tree-il->glil
146 ;; unreferenced sets may be optimized away -- make sure they are ref'd
147 (let (x) (y) ((const 1))
148 (set! (lexical x y) (primcall 1+ (lexical x y))))
149 (program () (std-prelude 0 1 #f) (label _)
150 (const 1) (bind (x #t 0)) (lexical #t #t box 0)
151 (lexical #t #t ref 0) (call add1 1) (lexical #t #t set 0)
152 (void) (call return 1)
155 (assert-tree-il->glil
156 (let (x) (y) ((const 1))
157 (begin (set! (lexical x y) (primcall 1+ (lexical x y)))
159 (program () (std-prelude 0 1 #f) (label _)
160 (const 1) (bind (x #t 0)) (lexical #t #t box 0)
161 (lexical #t #t ref 0) (call add1 1) (lexical #t #t set 0)
162 (lexical #t #t ref 0) (call return 1)
165 (assert-tree-il->glil
166 (let (x) (y) ((const 1))
168 (set! (lexical x y) (primcall 1+ (lexical x y)))))
169 (program () (std-prelude 0 1 #f) (label _)
170 (const 1) (bind (x #t 0)) (lexical #t #t box 0)
171 (lexical #t #t ref 0) (call add1 1) (lexical #t #t set 0) (void)
172 (call null? 1) (call return 1)
175 (with-test-prefix "module refs"
176 (assert-tree-il->glil
178 (program () (std-prelude 0 0 #f) (label _)
179 (module public ref (foo) bar)
182 (assert-tree-il->glil
183 (begin (@ (foo) bar) (const #f))
184 (program () (std-prelude 0 0 #f) (label _)
185 (module public ref (foo) bar) (call drop 1)
186 (const #f) (call return 1)))
188 (assert-tree-il->glil
189 (primcall null? (@ (foo) bar))
190 (program () (std-prelude 0 0 #f) (label _)
191 (module public ref (foo) bar)
192 (call null? 1) (call return 1)))
194 (assert-tree-il->glil
196 (program () (std-prelude 0 0 #f) (label _)
197 (module private ref (foo) bar)
200 (assert-tree-il->glil
201 (begin (@@ (foo) bar) (const #f))
202 (program () (std-prelude 0 0 #f) (label _)
203 (module private ref (foo) bar) (call drop 1)
204 (const #f) (call return 1)))
206 (assert-tree-il->glil
207 (primcall null? (@@ (foo) bar))
208 (program () (std-prelude 0 0 #f) (label _)
209 (module private ref (foo) bar)
210 (call null? 1) (call return 1))))
212 (with-test-prefix "module sets"
213 (assert-tree-il->glil
214 (set! (@ (foo) bar) (const 2))
215 (program () (std-prelude 0 0 #f) (label _)
216 (const 2) (module public set (foo) bar)
217 (void) (call return 1)))
219 (assert-tree-il->glil
220 (begin (set! (@ (foo) bar) (const 2)) (const #f))
221 (program () (std-prelude 0 0 #f) (label _)
222 (const 2) (module public set (foo) bar)
223 (const #f) (call return 1)))
225 (assert-tree-il->glil
226 (primcall null? (set! (@ (foo) bar) (const 2)))
227 (program () (std-prelude 0 0 #f) (label _)
228 (const 2) (module public set (foo) bar)
229 (void) (call null? 1) (call return 1)))
231 (assert-tree-il->glil
232 (set! (@@ (foo) bar) (const 2))
233 (program () (std-prelude 0 0 #f) (label _)
234 (const 2) (module private set (foo) bar)
235 (void) (call return 1)))
237 (assert-tree-il->glil
238 (begin (set! (@@ (foo) bar) (const 2)) (const #f))
239 (program () (std-prelude 0 0 #f) (label _)
240 (const 2) (module private set (foo) bar)
241 (const #f) (call return 1)))
243 (assert-tree-il->glil
244 (primcall null? (set! (@@ (foo) bar) (const 2)))
245 (program () (std-prelude 0 0 #f) (label _)
246 (const 2) (module private set (foo) bar)
247 (void) (call null? 1) (call return 1))))
249 (with-test-prefix "toplevel refs"
250 (assert-tree-il->glil
252 (program () (std-prelude 0 0 #f) (label _)
256 (assert-tree-il->glil
257 (begin (toplevel bar) (const #f))
258 (program () (std-prelude 0 0 #f) (label _)
259 (toplevel ref bar) (call drop 1)
260 (const #f) (call return 1)))
262 (assert-tree-il->glil
263 (primcall null? (toplevel bar))
264 (program () (std-prelude 0 0 #f) (label _)
266 (call null? 1) (call return 1))))
268 (with-test-prefix "toplevel sets"
269 (assert-tree-il->glil
270 (set! (toplevel bar) (const 2))
271 (program () (std-prelude 0 0 #f) (label _)
272 (const 2) (toplevel set bar)
273 (void) (call return 1)))
275 (assert-tree-il->glil
276 (begin (set! (toplevel bar) (const 2)) (const #f))
277 (program () (std-prelude 0 0 #f) (label _)
278 (const 2) (toplevel set bar)
279 (const #f) (call return 1)))
281 (assert-tree-il->glil
282 (primcall null? (set! (toplevel bar) (const 2)))
283 (program () (std-prelude 0 0 #f) (label _)
284 (const 2) (toplevel set bar)
285 (void) (call null? 1) (call return 1))))
287 (with-test-prefix "toplevel defines"
288 (assert-tree-il->glil
289 (define bar (const 2))
290 (program () (std-prelude 0 0 #f) (label _)
291 (const 2) (toplevel define bar)
292 (void) (call return 1)))
294 (assert-tree-il->glil
295 (begin (define bar (const 2)) (const #f))
296 (program () (std-prelude 0 0 #f) (label _)
297 (const 2) (toplevel define bar)
298 (const #f) (call return 1)))
300 (assert-tree-il->glil
301 (primcall null? (define bar (const 2)))
302 (program () (std-prelude 0 0 #f) (label _)
303 (const 2) (toplevel define bar)
304 (void) (call null? 1) (call return 1))))
306 (with-test-prefix "constants"
307 (assert-tree-il->glil
309 (program () (std-prelude 0 0 #f) (label _)
310 (const 2) (call return 1)))
312 (assert-tree-il->glil
313 (begin (const 2) (const #f))
314 (program () (std-prelude 0 0 #f) (label _)
315 (const #f) (call return 1)))
317 (assert-tree-il->glil
318 (primcall null? (const 2))
319 (program () (std-prelude 0 0 #f) (label _)
320 (const 2) (call null? 1) (call return 1))))
322 (with-test-prefix "letrec"
323 ;; simple bindings -> let
324 (assert-tree-il->glil
325 (letrec (x y) (x1 y1) ((const 10) (const 20))
326 (call (toplevel foo) (lexical x x1) (lexical y y1)))
327 (program () (std-prelude 0 2 #f) (label _)
328 (const 10) (const 20)
329 (bind (x #f 0) (y #f 1))
330 (lexical #t #f set 1) (lexical #t #f set 0)
332 (lexical #t #f ref 0) (lexical #t #f ref 1)
336 ;; complex bindings -> box and set! within let
337 (assert-tree-il->glil
338 (letrec (x y) (x1 y1) ((call (toplevel foo)) (call (toplevel bar)))
339 (primcall + (lexical x x1) (lexical y y1)))
340 (program () (std-prelude 0 4 #f) (label _)
341 (void) (void) ;; what are these?
342 (bind (x #t 0) (y #t 1))
343 (lexical #t #t box 1) (lexical #t #t box 0)
344 (call new-frame 0) (toplevel ref foo) (call call 0)
345 (call new-frame 0) (toplevel ref bar) (call call 0)
346 (bind (x #f 2) (y #f 3)) (lexical #t #f set 3) (lexical #t #f set 2)
347 (lexical #t #f ref 2) (lexical #t #t set 0)
348 (lexical #t #f ref 3) (lexical #t #t set 1) (unbind)
349 (lexical #t #t ref 0) (lexical #t #t ref 1)
350 (call add 2) (call return 1) (unbind)))
352 ;; complex bindings in letrec* -> box and set! in order
353 (assert-tree-il->glil
354 (letrec* (x y) (x1 y1) ((call (toplevel foo)) (call (toplevel bar)))
355 (primcall + (lexical x x1) (lexical y y1)))
356 (program () (std-prelude 0 2 #f) (label _)
357 (void) (void) ;; what are these?
358 (bind (x #t 0) (y #t 1))
359 (lexical #t #t box 1) (lexical #t #t box 0)
360 (call new-frame 0) (toplevel ref foo) (call call 0)
361 (lexical #t #t set 0)
362 (call new-frame 0) (toplevel ref bar) (call call 0)
363 (lexical #t #t set 1)
364 (lexical #t #t ref 0)
365 (lexical #t #t ref 1)
366 (call add 2) (call return 1) (unbind)))
368 ;; simple bindings in letrec* -> equivalent to letrec
369 (assert-tree-il->glil
370 (letrec* (x y) (xx yy) ((const 1) (const 2))
372 (program () (std-prelude 0 1 #f) (label _)
374 (bind (y #f 0)) ;; X is removed, and Y is unboxed
375 (lexical #t #f set 0)
376 (lexical #t #f ref 0)
377 (call return 1) (unbind))))
379 (with-test-prefix "lambda"
380 (assert-tree-il->glil
382 (lambda-case (((x) #f #f #f () (y)) (const 2)) #f))
383 (program () (std-prelude 0 0 #f) (label _)
384 (program () (std-prelude 1 1 #f)
385 (bind (x #f 0)) (label _)
386 (const 2) (call return 1) (unbind))
389 (assert-tree-il->glil
391 (lambda-case (((x y) #f #f #f () (x1 y1))
394 (program () (std-prelude 0 0 #f) (label _)
395 (program () (std-prelude 2 2 #f)
396 (bind (x #f 0) (y #f 1)) (label _)
397 (const 2) (call return 1)
401 (assert-tree-il->glil
403 (lambda-case ((() #f x #f () (y)) (const 2))
405 (program () (std-prelude 0 0 #f) (label _)
406 (program () (opt-prelude 0 0 0 1 #f)
407 (bind (x #f 0)) (label _)
408 (const 2) (call return 1)
412 (assert-tree-il->glil
414 (lambda-case (((x) #f x1 #f () (y y1)) (const 2))
416 (program () (std-prelude 0 0 #f) (label _)
417 (program () (opt-prelude 1 0 1 2 #f)
418 (bind (x #f 0) (x1 #f 1)) (label _)
419 (const 2) (call return 1)
423 (assert-tree-il->glil
425 (lambda-case (((x) #f x1 #f () (y y1)) (lexical x y))
427 (program () (std-prelude 0 0 #f) (label _)
428 (program () (opt-prelude 1 0 1 2 #f)
429 (bind (x #f 0) (x1 #f 1)) (label _)
430 (lexical #t #f ref 0) (call return 1)
434 (assert-tree-il->glil
436 (lambda-case (((x) #f x1 #f () (y y1)) (lexical x1 y1))
438 (program () (std-prelude 0 0 #f) (label _)
439 (program () (opt-prelude 1 0 1 2 #f)
440 (bind (x #f 0) (x1 #f 1)) (label _)
441 (lexical #t #f ref 1) (call return 1)
445 (assert-tree-il->glil
447 (lambda-case (((x) #f #f #f () (x1))
449 (lambda-case (((y) #f #f #f () (y1))
453 (program () (std-prelude 0 0 #f) (label _)
454 (program () (std-prelude 1 1 #f)
455 (bind (x #f 0)) (label _)
456 (program () (std-prelude 1 1 #f)
457 (bind (y #f 0)) (label _)
458 (lexical #f #f ref 0) (call return 1)
460 (lexical #t #f ref 0)
461 (call make-closure 1)
466 (with-test-prefix "sequence"
467 (assert-tree-il->glil
468 (begin (begin (const 2) (const #f)) (const #t))
469 (program () (std-prelude 0 0 #f) (label _)
470 (const #t) (call return 1)))
472 (assert-tree-il->glil
473 (primcall null? (begin (const #f) (const 2)))
474 (program () (std-prelude 0 0 #f) (label _)
475 (const 2) (call null? 1) (call return 1))))
477 ;; FIXME: binding info for or-hacked locals might bork the disassembler,
478 ;; and could be tightened in any case
479 (with-test-prefix "the or hack"
480 (assert-tree-il->glil
481 (let (x) (y) ((const 1))
484 (let (a) (b) ((const 2))
486 (program () (std-prelude 0 1 #f) (label _)
487 (const 1) (bind (x #f 0)) (lexical #t #f set 0)
488 (lexical #t #f ref 0) (branch br-if-not ,l1)
489 (lexical #t #f ref 0) (call return 1)
491 (const 2) (bind (a #f 0)) (lexical #t #f set 0)
492 (lexical #t #f ref 0) (call return 1)
497 ;; second bound var is unreferenced
498 (assert-tree-il->glil
499 (let (x) (y) ((const 1))
502 (let (a) (b) ((const 2))
504 (program () (std-prelude 0 1 #f) (label _)
505 (const 1) (bind (x #f 0)) (lexical #t #f set 0)
506 (lexical #t #f ref 0) (branch br-if-not ,l1)
507 (lexical #t #f ref 0) (call return 1)
509 (lexical #t #f ref 0) (call return 1)
513 (with-test-prefix "apply"
514 (assert-tree-il->glil
515 (primcall @apply (toplevel foo) (toplevel bar))
516 (program () (std-prelude 0 0 #f) (label _) (toplevel ref foo) (toplevel ref bar) (call tail-apply 2)))
517 (assert-tree-il->glil
518 (begin (primcall @apply (toplevel foo) (toplevel bar)) (void))
519 (program () (std-prelude 0 0 #f) (label _)
520 (call new-frame 0) (toplevel ref apply) (toplevel ref foo) (toplevel ref bar) (mv-call 2 ,l1)
521 (call drop 1) (branch br ,l2) (label ,l3) (mv-bind 0 #f)
523 (void) (call return 1))
524 (and (eq? l1 l3) (eq? l2 l4)))
525 (assert-tree-il->glil
526 (call (toplevel foo) (call (toplevel @apply) (toplevel bar) (toplevel baz)))
527 (program () (std-prelude 0 0 #f) (label _)
529 (call new-frame 0) (toplevel ref bar) (toplevel ref baz) (call apply 2)
530 (call tail-call 1))))
532 (with-test-prefix "call/cc"
533 (assert-tree-il->glil
534 (primcall @call-with-current-continuation (toplevel foo))
535 (program () (std-prelude 0 0 #f) (label _) (toplevel ref foo) (call tail-call/cc 1)))
536 (assert-tree-il->glil
537 (begin (primcall @call-with-current-continuation (toplevel foo)) (void))
538 (program () (std-prelude 0 0 #f) (label _)
539 (call new-frame 0) (toplevel ref call-with-current-continuation) (toplevel ref foo) (mv-call 1 ,l1)
540 (call drop 1) (branch br ,l2) (label ,l3) (mv-bind 0 #f)
542 (void) (call return 1))
543 (and (eq? l1 l3) (eq? l2 l4)))
544 (assert-tree-il->glil
546 (call (toplevel @call-with-current-continuation) (toplevel bar)))
547 (program () (std-prelude 0 0 #f) (label _)
549 (toplevel ref bar) (call call/cc 1)
550 (call tail-call 1))))
553 (with-test-prefix "tree-il-fold"
555 (pass-if "empty tree"
556 (let ((leaf? #f) (up? #f) (down? #f) (mark (list 'mark)))
558 (tree-il-fold (lambda (x y) (set! leaf? #t) y)
559 (lambda (x y) (set! down? #t) y)
560 (lambda (x y) (set! up? #t) y)
567 (pass-if "lambda and application"
568 (let* ((leaves '()) (ups '()) (downs '())
569 (result (tree-il-fold (lambda (x y)
570 (set! leaves (cons x leaves))
573 (set! downs (cons x downs))
576 (set! ups (cons x ups))
582 (((x y) #f #f #f () (x1 y1))
587 (and (equal? (map strip-source leaves)
588 (list (make-lexical-ref #f 'y 'y1)
589 (make-lexical-ref #f 'x 'x1)
590 (make-toplevel-ref #f '+)))
592 (equal? (reverse (map strip-source ups))
593 (map strip-source downs))))))
600 ;; Make sure we get English messages.
601 (setlocale LC_ALL "C")
603 (define (call-with-warnings thunk)
604 (let ((port (open-output-string)))
605 (with-fluids ((*current-warning-port* port)
606 (*current-warning-prefix* ""))
608 (let ((warnings (get-output-string port)))
609 (string-tokenize warnings
610 (char-set-complement (char-set #\newline))))))
612 (define %opts-w-unused
613 '(#:warnings (unused-variable)))
615 (define %opts-w-unused-toplevel
616 '(#:warnings (unused-toplevel)))
618 (define %opts-w-unbound
619 '(#:warnings (unbound-variable)))
621 (define %opts-w-arity
622 '(#:warnings (arity-mismatch)))
624 (define %opts-w-format
625 '(#:warnings (format)))
628 (with-test-prefix "warnings"
630 (pass-if "unknown warning type"
631 (let ((w (call-with-warnings
633 (compile #t #:opts '(#:warnings (does-not-exist)))))))
634 (and (= (length w) 1)
635 (number? (string-contains (car w) "unknown warning")))))
637 (with-test-prefix "unused-variable"
640 (null? (call-with-warnings
642 (compile '(lambda (x y) (+ x y))
643 #:opts %opts-w-unused)))))
645 (pass-if "let/unused"
646 (let ((w (call-with-warnings
648 (compile '(lambda (x)
651 #:opts %opts-w-unused)))))
652 (and (= (length w) 1)
653 (number? (string-contains (car w) "unused variable `y'")))))
655 (pass-if "shadowed variable"
656 (let ((w (call-with-warnings
658 (compile '(lambda (x)
662 #:opts %opts-w-unused)))))
663 (and (= (length w) 1)
664 (number? (string-contains (car w) "unused variable `y'")))))
667 (null? (call-with-warnings
670 (letrec ((x (lambda () (y)))
673 #:opts %opts-w-unused)))))
675 (pass-if "unused argument"
676 ;; Unused arguments should not be reported.
677 (null? (call-with-warnings
679 (compile '(lambda (x y z) #t)
680 #:opts %opts-w-unused)))))
682 (pass-if "special variable names"
683 (null? (call-with-warnings
686 (let ((_ 'underscore)
687 (#{gensym name}# 'ignore-me))
690 #:opts %opts-w-unused))))))
692 (with-test-prefix "unused-toplevel"
694 (pass-if "used after definition"
695 (null? (call-with-warnings
697 (let ((in (open-input-string
698 "(define foo 2) foo")))
701 #:opts %opts-w-unused-toplevel))))))
703 (pass-if "used before definition"
704 (null? (call-with-warnings
706 (let ((in (open-input-string
707 "(define (bar) foo) (define foo 2) (bar)")))
710 #:opts %opts-w-unused-toplevel))))))
712 (pass-if "unused but public"
713 (let ((in (open-input-string
714 "(define-module (test-suite tree-il x) #:export (bar))
715 (define (bar) #t)")))
716 (null? (call-with-warnings
720 #:opts %opts-w-unused-toplevel))))))
722 (pass-if "unused but public (more)"
723 (let ((in (open-input-string
724 "(define-module (test-suite tree-il x) #:export (bar))
727 (define (foo) #t)")))
728 (null? (call-with-warnings
732 #:opts %opts-w-unused-toplevel))))))
734 (pass-if "unused but define-public"
735 (null? (call-with-warnings
737 (compile '(define-public foo 2)
739 #:opts %opts-w-unused-toplevel)))))
741 (pass-if "used by macro"
742 ;; FIXME: See comment about macros at `unused-toplevel-analysis'.
745 (null? (call-with-warnings
747 (let ((in (open-input-string
750 (syntax-rules () ((_) (bar))))")))
753 #:opts %opts-w-unused-toplevel))))))
756 (let ((w (call-with-warnings
758 (compile '(define foo 2)
760 #:opts %opts-w-unused-toplevel)))))
761 (and (= (length w) 1)
762 (number? (string-contains (car w)
763 (format #f "top-level variable `~A'"
766 (pass-if "unused recursive"
767 (let ((w (call-with-warnings
769 (compile '(define (foo) (foo))
771 #:opts %opts-w-unused-toplevel)))))
772 (and (= (length w) 1)
773 (number? (string-contains (car w)
774 (format #f "top-level variable `~A'"
777 (pass-if "unused mutually recursive"
778 (let* ((in (open-input-string
779 "(define (foo) (bar)) (define (bar) (foo))"))
780 (w (call-with-warnings
784 #:opts %opts-w-unused-toplevel)))))
785 (and (= (length w) 2)
786 (number? (string-contains (car w)
787 (format #f "top-level variable `~A'"
789 (number? (string-contains (cadr w)
790 (format #f "top-level variable `~A'"
793 (pass-if "special variable names"
794 (null? (call-with-warnings
796 (compile '(define #{gensym name}# 'ignore-me)
798 #:opts %opts-w-unused-toplevel))))))
800 (with-test-prefix "unbound variable"
803 (null? (call-with-warnings
805 (compile '+ #:opts %opts-w-unbound)))))
809 (w (call-with-warnings
813 #:opts %opts-w-unbound)))))
814 (and (= (length w) 1)
815 (number? (string-contains (car w)
816 (format #f "unbound variable `~A'"
821 (w (call-with-warnings
823 (compile `(set! ,v 7)
825 #:opts %opts-w-unbound)))))
826 (and (= (length w) 1)
827 (number? (string-contains (car w)
828 (format #f "unbound variable `~A'"
831 (pass-if "module-local top-level is visible"
832 (let ((m (make-module))
834 (beautify-user-module! m)
835 (compile `(define ,v 123)
836 #:env m #:opts %opts-w-unbound)
837 (null? (call-with-warnings
842 #:opts %opts-w-unbound))))))
844 (pass-if "module-local top-level is visible after"
845 (let ((m (make-module))
847 (beautify-user-module! m)
848 (null? (call-with-warnings
850 (let ((in (open-input-string
853 (define chbouib 5)")))
856 #:opts %opts-w-unbound)))))))
858 (pass-if "optional arguments are visible"
859 (null? (call-with-warnings
861 (compile '(lambda* (x #:optional y z) (list x y z))
862 #:opts %opts-w-unbound
865 (pass-if "keyword arguments are visible"
866 (null? (call-with-warnings
868 (compile '(lambda* (x #:key y z) (list x y z))
869 #:opts %opts-w-unbound
872 (pass-if "GOOPS definitions are visible"
873 (let ((m (make-module))
875 (beautify-user-module! m)
876 (module-use! m (resolve-interface '(oop goops)))
877 (null? (call-with-warnings
879 (let ((in (open-input-string
880 "(define-class <foo> ()
881 (bar #:getter foo-bar))
882 (define z (foo-bar (make <foo>)))")))
885 #:opts %opts-w-unbound))))))))
887 (with-test-prefix "arity mismatch"
890 (null? (call-with-warnings
892 (compile '(cons 'a 'b) #:opts %opts-w-arity)))))
894 (pass-if "direct application"
895 (let ((w (call-with-warnings
897 (compile '((lambda (x y) (or x y)) 1 2 3 4 5)
900 (and (= (length w) 1)
901 (number? (string-contains (car w)
902 "wrong number of arguments to")))))
904 (let ((w (call-with-warnings
906 (compile '(let ((f (lambda (x y) (+ x y))))
910 (and (= (length w) 1)
911 (number? (string-contains (car w)
912 "wrong number of arguments to")))))
915 (let ((w (call-with-warnings
917 (compile '(cons 1 2 3 4)
920 (and (= (length w) 1)
921 (number? (string-contains (car w)
922 "wrong number of arguments to")))))
924 (pass-if "alias to global"
925 (let ((w (call-with-warnings
927 (compile '(let ((f cons)) (f 1 2 3 4))
930 (and (= (length w) 1)
931 (number? (string-contains (car w)
932 "wrong number of arguments to")))))
934 (pass-if "alias to lexical to global"
935 (let ((w (call-with-warnings
937 (compile '(let ((f number?))
942 (and (= (length w) 1)
943 (number? (string-contains (car w)
944 "wrong number of arguments to")))))
946 (pass-if "alias to lexical"
947 (let ((w (call-with-warnings
949 (compile '(let ((f (lambda (x y z) (+ x y z))))
954 (and (= (length w) 1)
955 (number? (string-contains (car w)
956 "wrong number of arguments to")))))
959 (let ((w (call-with-warnings
961 (compile '(letrec ((odd? (lambda (x) (even? (1- x))))
968 (and (= (length w) 1)
969 (number? (string-contains (car w)
970 "wrong number of arguments to")))))
972 (pass-if "case-lambda"
973 (null? (call-with-warnings
975 (compile '(let ((f (case-lambda
985 (pass-if "case-lambda with wrong number of arguments"
986 (let ((w (call-with-warnings
988 (compile '(let ((f (case-lambda
994 (and (= (length w) 1)
995 (number? (string-contains (car w)
996 "wrong number of arguments to")))))
998 (pass-if "case-lambda*"
999 (null? (call-with-warnings
1001 (compile '(let ((f (case-lambda*
1002 ((x #:optional y) 1)
1004 ((x y #:key z) 3))))
1009 #:opts %opts-w-arity
1012 (pass-if "case-lambda* with wrong arguments"
1013 (let ((w (call-with-warnings
1015 (compile '(let ((f (case-lambda*
1016 ((x #:optional y) 1)
1018 ((x y #:key z) 3))))
1021 #:opts %opts-w-arity
1023 (and (= (length w) 2)
1024 (null? (filter (lambda (w)
1028 w "wrong number of arguments to"))))
1031 (pass-if "local toplevel-defines"
1032 (let ((w (call-with-warnings
1034 (let ((in (open-input-string "
1035 (define (g x) (f x))
1037 (read-and-compile in
1038 #:opts %opts-w-arity
1039 #:to 'assembly))))))
1040 (and (= (length w) 1)
1041 (number? (string-contains (car w)
1042 "wrong number of arguments to")))))
1044 (pass-if "global toplevel alias"
1045 (let ((w (call-with-warnings
1047 (let ((in (open-input-string "
1049 (define (g) (f))")))
1050 (read-and-compile in
1051 #:opts %opts-w-arity
1052 #:to 'assembly))))))
1053 (and (= (length w) 1)
1054 (number? (string-contains (car w)
1055 "wrong number of arguments to")))))
1057 (pass-if "local toplevel overrides global"
1058 (null? (call-with-warnings
1060 (let ((in (open-input-string "
1062 (define (foo x) (cons))")))
1063 (read-and-compile in
1064 #:opts %opts-w-arity
1065 #:to 'assembly))))))
1067 (pass-if "keyword not passed and quiet"
1068 (null? (call-with-warnings
1070 (compile '(let ((f (lambda* (x #:key y) y)))
1072 #:opts %opts-w-arity
1075 (pass-if "keyword passed and quiet"
1076 (null? (call-with-warnings
1078 (compile '(let ((f (lambda* (x #:key y) y)))
1080 #:opts %opts-w-arity
1083 (pass-if "keyword passed to global and quiet"
1084 (null? (call-with-warnings
1086 (let ((in (open-input-string "
1087 (use-modules (system base compile))
1088 (compile '(+ 2 3) #:env (current-module))")))
1089 (read-and-compile in
1090 #:opts %opts-w-arity
1091 #:to 'assembly))))))
1093 (pass-if "extra keyword"
1094 (let ((w (call-with-warnings
1096 (compile '(let ((f (lambda* (x #:key y) y)))
1098 #:opts %opts-w-arity
1100 (and (= (length w) 1)
1101 (number? (string-contains (car w)
1102 "wrong number of arguments to")))))
1104 (pass-if "extra keywords allowed"
1105 (null? (call-with-warnings
1107 (compile '(let ((f (lambda* (x #:key y #:allow-other-keys)
1110 #:opts %opts-w-arity
1111 #:to 'assembly))))))
1113 (with-test-prefix "format"
1115 (pass-if "quiet (no args)"
1116 (null? (call-with-warnings
1118 (compile '(format #t "hey!")
1119 #:opts %opts-w-format
1122 (pass-if "quiet (1 arg)"
1123 (null? (call-with-warnings
1125 (compile '(format #t "hey ~A!" "you")
1126 #:opts %opts-w-format
1129 (pass-if "quiet (2 args)"
1130 (null? (call-with-warnings
1132 (compile '(format #t "~A ~A!" "hello" "world")
1133 #:opts %opts-w-format
1136 (pass-if "wrong port arg"
1137 (let ((w (call-with-warnings
1139 (compile '(format 10 "foo")
1140 #:opts %opts-w-format
1142 (and (= (length w) 1)
1143 (number? (string-contains (car w)
1144 "wrong port argument")))))
1146 (pass-if "non-literal format string"
1147 (let ((w (call-with-warnings
1149 (compile '(format #f fmt)
1150 #:opts %opts-w-format
1152 (and (= (length w) 1)
1153 (number? (string-contains (car w)
1154 "non-literal format string")))))
1156 (pass-if "non-literal format string using gettext"
1157 (null? (call-with-warnings
1159 (compile '(format #t (_ "~A ~A!") "hello" "world")
1160 #:opts %opts-w-format
1163 (pass-if "wrong format string"
1164 (let ((w (call-with-warnings
1166 (compile '(format #f 'not-a-string)
1167 #:opts %opts-w-format
1169 (and (= (length w) 1)
1170 (number? (string-contains (car w)
1171 "wrong format string")))))
1173 (pass-if "wrong number of args"
1174 (let ((w (call-with-warnings
1176 (compile '(format "shbweeb")
1177 #:opts %opts-w-format
1179 (and (= (length w) 1)
1180 (number? (string-contains (car w)
1181 "wrong number of arguments")))))
1183 (pass-if "~%, ~~, ~&, ~t, ~_, and ~\\n"
1184 (null? (call-with-warnings
1186 (compile '(format some-port "~&~3_~~ ~\n~12they~%")
1187 #:opts %opts-w-format
1190 (pass-if "one missing argument"
1191 (let ((w (call-with-warnings
1193 (compile '(format some-port "foo ~A~%")
1194 #:opts %opts-w-format
1196 (and (= (length w) 1)
1197 (number? (string-contains (car w)
1198 "expected 1, got 0")))))
1200 (pass-if "one missing argument, gettext"
1201 (let ((w (call-with-warnings
1203 (compile '(format some-port (_ "foo ~A~%"))
1204 #:opts %opts-w-format
1206 (and (= (length w) 1)
1207 (number? (string-contains (car w)
1208 "expected 1, got 0")))))
1210 (pass-if "two missing arguments"
1211 (let ((w (call-with-warnings
1213 (compile '(format #f "foo ~10,2f and bar ~S~%")
1214 #:opts %opts-w-format
1216 (and (= (length w) 1)
1217 (number? (string-contains (car w)
1218 "expected 2, got 0")))))
1220 (pass-if "one given, one missing argument"
1221 (let ((w (call-with-warnings
1223 (compile '(format #t "foo ~A and ~S~%" hey)
1224 #:opts %opts-w-format
1226 (and (= (length w) 1)
1227 (number? (string-contains (car w)
1228 "expected 2, got 1")))))
1230 (pass-if "too many arguments"
1231 (let ((w (call-with-warnings
1233 (compile '(format #t "foo ~A~%" 1 2)
1234 #:opts %opts-w-format
1236 (and (= (length w) 1)
1237 (number? (string-contains (car w)
1238 "expected 1, got 2")))))
1240 (with-test-prefix "conditionals"
1242 (null? (call-with-warnings
1244 (compile '(format #f "~A ~[foo~;bar~;baz~;~] ~10,2f"
1246 #:opts %opts-w-format
1249 (pass-if "literals with selector"
1250 (let ((w (call-with-warnings
1252 (compile '(format #f "~2[foo~;bar~;baz~;~] ~A"
1254 #:opts %opts-w-format
1256 (and (= (length w) 1)
1257 (number? (string-contains (car w)
1258 "expected 1, got 2")))))
1260 (pass-if "escapes (exact count)"
1261 (let ((w (call-with-warnings
1263 (compile '(format #f "~[~a~;~a~]")
1264 #:opts %opts-w-format
1266 (and (= (length w) 1)
1267 (number? (string-contains (car w)
1268 "expected 2, got 0")))))
1270 (pass-if "escapes with selector"
1271 (let ((w (call-with-warnings
1273 (compile '(format #f "~1[chbouib~;~a~]")
1274 #:opts %opts-w-format
1276 (and (= (length w) 1)
1277 (number? (string-contains (car w)
1278 "expected 1, got 0")))))
1280 (pass-if "escapes, range"
1281 (let ((w (call-with-warnings
1283 (compile '(format #f "~[chbouib~;~a~;~2*~a~]")
1284 #:opts %opts-w-format
1286 (and (= (length w) 1)
1287 (number? (string-contains (car w)
1288 "expected 1 to 4, got 0")))))
1291 (let ((w (call-with-warnings
1293 (compile '(format #f "~@[temperature=~d~]")
1294 #:opts %opts-w-format
1296 (and (= (length w) 1)
1297 (number? (string-contains (car w)
1298 "expected 1, got 0")))))
1301 (let ((w (call-with-warnings
1303 (compile '(format #f "~:[~[hey~;~a~;~va~]~;~3*~]")
1304 #:opts %opts-w-format
1306 (and (= (length w) 1)
1307 (number? (string-contains (car w)
1308 "expected 2 to 4, got 0")))))
1310 (pass-if "unterminated"
1311 (let ((w (call-with-warnings
1313 (compile '(format #f "~[unterminated")
1314 #:opts %opts-w-format
1316 (and (= (length w) 1)
1317 (number? (string-contains (car w)
1318 "unterminated conditional")))))
1320 (pass-if "unexpected ~;"
1321 (let ((w (call-with-warnings
1323 (compile '(format #f "foo~;bar")
1324 #:opts %opts-w-format
1326 (and (= (length w) 1)
1327 (number? (string-contains (car w)
1330 (pass-if "unexpected ~]"
1331 (let ((w (call-with-warnings
1333 (compile '(format #f "foo~]")
1334 #:opts %opts-w-format
1336 (and (= (length w) 1)
1337 (number? (string-contains (car w)
1341 (null? (call-with-warnings
1343 (compile '(format #f "~A ~{~S~} ~A"
1344 'hello '("ladies" "and")
1346 #:opts %opts-w-format
1349 (pass-if "~{...~}, too many args"
1350 (let ((w (call-with-warnings
1352 (compile '(format #f "~{~S~}" 1 2 3)
1353 #:opts %opts-w-format
1355 (and (= (length w) 1)
1356 (number? (string-contains (car w)
1357 "expected 1, got 3")))))
1360 (null? (call-with-warnings
1362 (compile '(format #f "~@{~S~}" 1 2 3)
1363 #:opts %opts-w-format
1366 (pass-if "~@{...~}, too few args"
1367 (let ((w (call-with-warnings
1369 (compile '(format #f "~A ~@{~S~}")
1370 #:opts %opts-w-format
1372 (and (= (length w) 1)
1373 (number? (string-contains (car w)
1374 "expected at least 1, got 0")))))
1376 (pass-if "unterminated ~{...~}"
1377 (let ((w (call-with-warnings
1379 (compile '(format #f "~{")
1380 #:opts %opts-w-format
1382 (and (= (length w) 1)
1383 (number? (string-contains (car w)
1387 (null? (call-with-warnings
1389 (compile '(format #f "~:@(~A ~A~)" 'foo 'bar)
1390 #:opts %opts-w-format
1394 (let ((w (call-with-warnings
1396 (compile '(format #f "~v_foo")
1397 #:opts %opts-w-format
1399 (and (= (length w) 1)
1400 (number? (string-contains (car w)
1401 "expected 1, got 0")))))
1403 (null? (call-with-warnings
1405 (compile '(format #f "~v:@y" 1 123)
1406 #:opts %opts-w-format
1411 (let ((w (call-with-warnings
1413 (compile '(format #f "~2*~a" 'a 'b)
1414 #:opts %opts-w-format
1416 (and (= (length w) 1)
1417 (number? (string-contains (car w)
1418 "expected 3, got 2")))))
1421 (null? (call-with-warnings
1423 (compile '(format #f "~?" "~d ~d" '(1 2))
1424 #:opts %opts-w-format
1427 (pass-if "complex 1"
1428 (let ((w (call-with-warnings
1430 (compile '(format #f
1431 "~4@S ~32S~@[;; ~1{~@?~}~]~@[~61t at ~a~]\n"
1433 #:opts %opts-w-format
1435 (and (= (length w) 1)
1436 (number? (string-contains (car w)
1437 "expected 4, got 6")))))
1439 (pass-if "complex 2"
1440 (let ((w (call-with-warnings
1442 (compile '(format #f
1443 "~:(~A~) Commands~:[~; [abbrev]~]:~2%"
1445 #:opts %opts-w-format
1447 (and (= (length w) 1)
1448 (number? (string-contains (car w)
1449 "expected 2, got 4")))))
1451 (pass-if "complex 3"
1452 (let ((w (call-with-warnings
1454 (compile '(format #f "~9@a~:[~*~3_~;~3d~] ~v:@y~%")
1455 #:opts %opts-w-format
1457 (and (= (length w) 1)
1458 (number? (string-contains (car w)
1459 "expected 5, got 0")))))
1461 (pass-if "ice-9 format"
1462 (let ((w (call-with-warnings
1464 (let ((in (open-input-string
1465 "(use-modules ((ice-9 format)
1466 #:renamer (symbol-prefix-proc 'i9-)))
1467 (i9-format #t \"yo! ~A\" 1 2)")))
1468 (read-and-compile in
1469 #:opts %opts-w-format
1470 #:to 'assembly))))))
1471 (and (= (length w) 1)
1472 (number? (string-contains (car w)
1473 "expected 1, got 2")))))
1475 (pass-if "not format"
1476 (null? (call-with-warnings
1478 (compile '(let ((format chbouib))
1479 (format #t "not ~A a format string"))
1480 #:opts %opts-w-format
1481 #:to 'assembly)))))))