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 (apply (primitive +) (void) (const 1))
67 (program () (std-prelude 0 0 #f) (label _) (void) (call add1 1) (call return 1))))
69 (with-test-prefix "application"
71 (apply (toplevel foo) (const 1))
72 (program () (std-prelude 0 0 #f) (label _) (toplevel ref foo) (const 1) (call tail-call 1)))
74 (begin (apply (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 (apply (toplevel foo) (apply (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 (apply (primitive 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 (apply (primitive 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)) (apply (primitive 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) (apply (primitive 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) (apply (primitive 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))
167 (apply (primitive null?)
168 (set! (lexical x y) (apply (primitive 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 (apply (primitive 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 (apply (primitive 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 (apply (primitive 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 (apply (primitive 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 (apply (primitive 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 (apply (primitive 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 (apply (primitive 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 (apply (primitive 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 (apply (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) ((apply (toplevel foo)) (apply (toplevel bar)))
339 (apply (primitive +) (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) ((apply (toplevel foo)) (apply (toplevel bar)))
355 (apply (primitive +) (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 (apply (primitive null?) (begin (const #f) (const 2)))
474 (program () (std-prelude 0 0 #f) (label _)
475 (const 2) (call null? 1) (call return 1))))
477 (with-test-prefix "values"
478 (assert-tree-il->glil
479 (apply (primitive values)
480 (apply (primitive values) (const 1) (const 2)))
481 (program () (std-prelude 0 0 #f) (label _)
482 (const 1) (call return 1)))
484 (assert-tree-il->glil
485 (apply (primitive values)
486 (apply (primitive values) (const 1) (const 2))
488 (program () (std-prelude 0 0 #f) (label _)
489 (const 1) (const 3) (call return/values 2)))
491 (assert-tree-il->glil
493 (apply (primitive values) (const 1) (const 2)))
494 (program () (std-prelude 0 0 #f) (label _)
495 (const 1) (call return 1))))
497 ;; FIXME: binding info for or-hacked locals might bork the disassembler,
498 ;; and could be tightened in any case
499 (with-test-prefix "the or hack"
500 (assert-tree-il->glil
501 (let (x) (y) ((const 1))
504 (let (a) (b) ((const 2))
506 (program () (std-prelude 0 1 #f) (label _)
507 (const 1) (bind (x #f 0)) (lexical #t #f set 0)
508 (lexical #t #f ref 0) (branch br-if-not ,l1)
509 (lexical #t #f ref 0) (call return 1)
511 (const 2) (bind (a #f 0)) (lexical #t #f set 0)
512 (lexical #t #f ref 0) (call return 1)
517 ;; second bound var is unreferenced
518 (assert-tree-il->glil
519 (let (x) (y) ((const 1))
522 (let (a) (b) ((const 2))
524 (program () (std-prelude 0 1 #f) (label _)
525 (const 1) (bind (x #f 0)) (lexical #t #f set 0)
526 (lexical #t #f ref 0) (branch br-if-not ,l1)
527 (lexical #t #f ref 0) (call return 1)
529 (lexical #t #f ref 0) (call return 1)
533 (with-test-prefix "apply"
534 (assert-tree-il->glil
535 (apply (primitive @apply) (toplevel foo) (toplevel bar))
536 (program () (std-prelude 0 0 #f) (label _) (toplevel ref foo) (toplevel ref bar) (call tail-apply 2)))
537 (assert-tree-il->glil
538 (begin (apply (primitive @apply) (toplevel foo) (toplevel bar)) (void))
539 (program () (std-prelude 0 0 #f) (label _)
540 (call new-frame 0) (toplevel ref apply) (toplevel ref foo) (toplevel ref bar) (mv-call 2 ,l1)
541 (call drop 1) (branch br ,l2) (label ,l3) (mv-bind 0 #f)
543 (void) (call return 1))
544 (and (eq? l1 l3) (eq? l2 l4)))
545 (assert-tree-il->glil
546 (apply (toplevel foo) (apply (toplevel @apply) (toplevel bar) (toplevel baz)))
547 (program () (std-prelude 0 0 #f) (label _)
549 (call new-frame 0) (toplevel ref bar) (toplevel ref baz) (call apply 2)
550 (call tail-call 1))))
552 (with-test-prefix "call/cc"
553 (assert-tree-il->glil
554 (apply (primitive @call-with-current-continuation) (toplevel foo))
555 (program () (std-prelude 0 0 #f) (label _) (toplevel ref foo) (call tail-call/cc 1)))
556 (assert-tree-il->glil
557 (begin (apply (primitive @call-with-current-continuation) (toplevel foo)) (void))
558 (program () (std-prelude 0 0 #f) (label _)
559 (call new-frame 0) (toplevel ref call-with-current-continuation) (toplevel ref foo) (mv-call 1 ,l1)
560 (call drop 1) (branch br ,l2) (label ,l3) (mv-bind 0 #f)
562 (void) (call return 1))
563 (and (eq? l1 l3) (eq? l2 l4)))
564 (assert-tree-il->glil
565 (apply (toplevel foo)
566 (apply (toplevel @call-with-current-continuation) (toplevel bar)))
567 (program () (std-prelude 0 0 #f) (label _)
569 (toplevel ref bar) (call call/cc 1)
570 (call tail-call 1))))
573 (with-test-prefix "tree-il-fold"
575 (pass-if "empty tree"
576 (let ((leaf? #f) (up? #f) (down? #f) (mark (list 'mark)))
578 (tree-il-fold (lambda (x y) (set! leaf? #t) y)
579 (lambda (x y) (set! down? #t) y)
580 (lambda (x y) (set! up? #t) y)
587 (pass-if "lambda and application"
588 (let* ((leaves '()) (ups '()) (downs '())
589 (result (tree-il-fold (lambda (x y)
590 (set! leaves (cons x leaves))
593 (set! downs (cons x downs))
596 (set! ups (cons x ups))
602 (((x y) #f #f #f () (x1 y1))
607 (and (equal? (map strip-source leaves)
608 (list (make-lexical-ref #f 'y 'y1)
609 (make-lexical-ref #f 'x 'x1)
610 (make-toplevel-ref #f '+)))
612 (equal? (reverse (map strip-source ups))
613 (map strip-source downs))))))
620 ;; Make sure we get English messages.
621 (setlocale LC_ALL "C")
623 (define (call-with-warnings thunk)
624 (let ((port (open-output-string)))
625 (with-fluids ((*current-warning-port* port)
626 (*current-warning-prefix* ""))
628 (let ((warnings (get-output-string port)))
629 (string-tokenize warnings
630 (char-set-complement (char-set #\newline))))))
632 (define %opts-w-unused
633 '(#:warnings (unused-variable)))
635 (define %opts-w-unused-toplevel
636 '(#:warnings (unused-toplevel)))
638 (define %opts-w-unbound
639 '(#:warnings (unbound-variable)))
641 (define %opts-w-arity
642 '(#:warnings (arity-mismatch)))
644 (define %opts-w-format
645 '(#:warnings (format)))
648 (with-test-prefix "warnings"
650 (pass-if "unknown warning type"
651 (let ((w (call-with-warnings
653 (compile #t #:opts '(#:warnings (does-not-exist)))))))
654 (and (= (length w) 1)
655 (number? (string-contains (car w) "unknown warning")))))
657 (with-test-prefix "unused-variable"
660 (null? (call-with-warnings
662 (compile '(lambda (x y) (+ x y))
663 #:opts %opts-w-unused)))))
665 (pass-if "let/unused"
666 (let ((w (call-with-warnings
668 (compile '(lambda (x)
671 #:opts %opts-w-unused)))))
672 (and (= (length w) 1)
673 (number? (string-contains (car w) "unused variable `y'")))))
675 (pass-if "shadowed variable"
676 (let ((w (call-with-warnings
678 (compile '(lambda (x)
682 #:opts %opts-w-unused)))))
683 (and (= (length w) 1)
684 (number? (string-contains (car w) "unused variable `y'")))))
687 (null? (call-with-warnings
690 (letrec ((x (lambda () (y)))
693 #:opts %opts-w-unused)))))
695 (pass-if "unused argument"
696 ;; Unused arguments should not be reported.
697 (null? (call-with-warnings
699 (compile '(lambda (x y z) #t)
700 #:opts %opts-w-unused)))))
702 (pass-if "special variable names"
703 (null? (call-with-warnings
706 (let ((_ 'underscore)
707 (#{gensym name}# 'ignore-me))
710 #:opts %opts-w-unused))))))
712 (with-test-prefix "unused-toplevel"
714 (pass-if "used after definition"
715 (null? (call-with-warnings
717 (let ((in (open-input-string
718 "(define foo 2) foo")))
721 #:opts %opts-w-unused-toplevel))))))
723 (pass-if "used before definition"
724 (null? (call-with-warnings
726 (let ((in (open-input-string
727 "(define (bar) foo) (define foo 2) (bar)")))
730 #:opts %opts-w-unused-toplevel))))))
732 (pass-if "unused but public"
733 (let ((in (open-input-string
734 "(define-module (test-suite tree-il x) #:export (bar))
735 (define (bar) #t)")))
736 (null? (call-with-warnings
740 #:opts %opts-w-unused-toplevel))))))
742 (pass-if "unused but public (more)"
743 (let ((in (open-input-string
744 "(define-module (test-suite tree-il x) #:export (bar))
747 (define (foo) #t)")))
748 (null? (call-with-warnings
752 #:opts %opts-w-unused-toplevel))))))
754 (pass-if "unused but define-public"
755 (null? (call-with-warnings
757 (compile '(define-public foo 2)
759 #:opts %opts-w-unused-toplevel)))))
761 (pass-if "used by macro"
762 ;; FIXME: See comment about macros at `unused-toplevel-analysis'.
765 (null? (call-with-warnings
767 (let ((in (open-input-string
770 (syntax-rules () ((_) (bar))))")))
773 #:opts %opts-w-unused-toplevel))))))
776 (let ((w (call-with-warnings
778 (compile '(define foo 2)
780 #:opts %opts-w-unused-toplevel)))))
781 (and (= (length w) 1)
782 (number? (string-contains (car w)
783 (format #f "top-level variable `~A'"
786 (pass-if "unused recursive"
787 (let ((w (call-with-warnings
789 (compile '(define (foo) (foo))
791 #:opts %opts-w-unused-toplevel)))))
792 (and (= (length w) 1)
793 (number? (string-contains (car w)
794 (format #f "top-level variable `~A'"
797 (pass-if "unused mutually recursive"
798 (let* ((in (open-input-string
799 "(define (foo) (bar)) (define (bar) (foo))"))
800 (w (call-with-warnings
804 #:opts %opts-w-unused-toplevel)))))
805 (and (= (length w) 2)
806 (number? (string-contains (car w)
807 (format #f "top-level variable `~A'"
809 (number? (string-contains (cadr w)
810 (format #f "top-level variable `~A'"
813 (pass-if "special variable names"
814 (null? (call-with-warnings
816 (compile '(define #{gensym name}# 'ignore-me)
818 #:opts %opts-w-unused-toplevel))))))
820 (with-test-prefix "unbound variable"
823 (null? (call-with-warnings
825 (compile '+ #:opts %opts-w-unbound)))))
829 (w (call-with-warnings
833 #:opts %opts-w-unbound)))))
834 (and (= (length w) 1)
835 (number? (string-contains (car w)
836 (format #f "unbound variable `~A'"
841 (w (call-with-warnings
843 (compile `(set! ,v 7)
845 #:opts %opts-w-unbound)))))
846 (and (= (length w) 1)
847 (number? (string-contains (car w)
848 (format #f "unbound variable `~A'"
851 (pass-if "module-local top-level is visible"
852 (let ((m (make-module))
854 (beautify-user-module! m)
855 (compile `(define ,v 123)
856 #:env m #:opts %opts-w-unbound)
857 (null? (call-with-warnings
862 #:opts %opts-w-unbound))))))
864 (pass-if "module-local top-level is visible after"
865 (let ((m (make-module))
867 (beautify-user-module! m)
868 (null? (call-with-warnings
870 (let ((in (open-input-string
873 (define chbouib 5)")))
876 #:opts %opts-w-unbound)))))))
878 (pass-if "optional arguments are visible"
879 (null? (call-with-warnings
881 (compile '(lambda* (x #:optional y z) (list x y z))
882 #:opts %opts-w-unbound
885 (pass-if "keyword arguments are visible"
886 (null? (call-with-warnings
888 (compile '(lambda* (x #:key y z) (list x y z))
889 #:opts %opts-w-unbound
892 (pass-if "GOOPS definitions are visible"
893 (let ((m (make-module))
895 (beautify-user-module! m)
896 (module-use! m (resolve-interface '(oop goops)))
897 (null? (call-with-warnings
899 (let ((in (open-input-string
900 "(define-class <foo> ()
901 (bar #:getter foo-bar))
902 (define z (foo-bar (make <foo>)))")))
905 #:opts %opts-w-unbound))))))))
907 (with-test-prefix "arity mismatch"
910 (null? (call-with-warnings
912 (compile '(cons 'a 'b) #:opts %opts-w-arity)))))
914 (pass-if "direct application"
915 (let ((w (call-with-warnings
917 (compile '((lambda (x y) (or x y)) 1 2 3 4 5)
920 (and (= (length w) 1)
921 (number? (string-contains (car w)
922 "wrong number of arguments to")))))
924 (let ((w (call-with-warnings
926 (compile '(let ((f (lambda (x y) (+ x y))))
930 (and (= (length w) 1)
931 (number? (string-contains (car w)
932 "wrong number of arguments to")))))
935 (let ((w (call-with-warnings
937 (compile '(cons 1 2 3 4)
940 (and (= (length w) 1)
941 (number? (string-contains (car w)
942 "wrong number of arguments to")))))
944 (pass-if "alias to global"
945 (let ((w (call-with-warnings
947 (compile '(let ((f cons)) (f 1 2 3 4))
950 (and (= (length w) 1)
951 (number? (string-contains (car w)
952 "wrong number of arguments to")))))
954 (pass-if "alias to lexical to global"
955 (let ((w (call-with-warnings
957 (compile '(let ((f number?))
962 (and (= (length w) 1)
963 (number? (string-contains (car w)
964 "wrong number of arguments to")))))
966 (pass-if "alias to lexical"
967 (let ((w (call-with-warnings
969 (compile '(let ((f (lambda (x y z) (+ x y z))))
974 (and (= (length w) 1)
975 (number? (string-contains (car w)
976 "wrong number of arguments to")))))
979 (let ((w (call-with-warnings
981 (compile '(letrec ((odd? (lambda (x) (even? (1- x))))
988 (and (= (length w) 1)
989 (number? (string-contains (car w)
990 "wrong number of arguments to")))))
992 (pass-if "case-lambda"
993 (null? (call-with-warnings
995 (compile '(let ((f (case-lambda
1002 #:opts %opts-w-arity
1005 (pass-if "case-lambda with wrong number of arguments"
1006 (let ((w (call-with-warnings
1008 (compile '(let ((f (case-lambda
1012 #:opts %opts-w-arity
1014 (and (= (length w) 1)
1015 (number? (string-contains (car w)
1016 "wrong number of arguments to")))))
1018 (pass-if "case-lambda*"
1019 (null? (call-with-warnings
1021 (compile '(let ((f (case-lambda*
1022 ((x #:optional y) 1)
1024 ((x y #:key z) 3))))
1029 #:opts %opts-w-arity
1032 (pass-if "case-lambda* with wrong arguments"
1033 (let ((w (call-with-warnings
1035 (compile '(let ((f (case-lambda*
1036 ((x #:optional y) 1)
1038 ((x y #:key z) 3))))
1041 #:opts %opts-w-arity
1043 (and (= (length w) 2)
1044 (null? (filter (lambda (w)
1048 w "wrong number of arguments to"))))
1051 (pass-if "local toplevel-defines"
1052 (let ((w (call-with-warnings
1054 (let ((in (open-input-string "
1055 (define (g x) (f x))
1057 (read-and-compile in
1058 #:opts %opts-w-arity
1059 #:to 'assembly))))))
1060 (and (= (length w) 1)
1061 (number? (string-contains (car w)
1062 "wrong number of arguments to")))))
1064 (pass-if "global toplevel alias"
1065 (let ((w (call-with-warnings
1067 (let ((in (open-input-string "
1069 (define (g) (f))")))
1070 (read-and-compile in
1071 #:opts %opts-w-arity
1072 #:to 'assembly))))))
1073 (and (= (length w) 1)
1074 (number? (string-contains (car w)
1075 "wrong number of arguments to")))))
1077 (pass-if "local toplevel overrides global"
1078 (null? (call-with-warnings
1080 (let ((in (open-input-string "
1082 (define (foo x) (cons))")))
1083 (read-and-compile in
1084 #:opts %opts-w-arity
1085 #:to 'assembly))))))
1087 (pass-if "keyword not passed and quiet"
1088 (null? (call-with-warnings
1090 (compile '(let ((f (lambda* (x #:key y) y)))
1092 #:opts %opts-w-arity
1095 (pass-if "keyword passed and quiet"
1096 (null? (call-with-warnings
1098 (compile '(let ((f (lambda* (x #:key y) y)))
1100 #:opts %opts-w-arity
1103 (pass-if "keyword passed to global and quiet"
1104 (null? (call-with-warnings
1106 (let ((in (open-input-string "
1107 (use-modules (system base compile))
1108 (compile '(+ 2 3) #:env (current-module))")))
1109 (read-and-compile in
1110 #:opts %opts-w-arity
1111 #:to 'assembly))))))
1113 (pass-if "extra keyword"
1114 (let ((w (call-with-warnings
1116 (compile '(let ((f (lambda* (x #:key y) y)))
1118 #:opts %opts-w-arity
1120 (and (= (length w) 1)
1121 (number? (string-contains (car w)
1122 "wrong number of arguments to")))))
1124 (pass-if "extra keywords allowed"
1125 (null? (call-with-warnings
1127 (compile '(let ((f (lambda* (x #:key y #:allow-other-keys)
1130 #:opts %opts-w-arity
1131 #:to 'assembly))))))
1133 (with-test-prefix "format"
1135 (pass-if "quiet (no args)"
1136 (null? (call-with-warnings
1138 (compile '(format #t "hey!")
1139 #:opts %opts-w-format
1142 (pass-if "quiet (1 arg)"
1143 (null? (call-with-warnings
1145 (compile '(format #t "hey ~A!" "you")
1146 #:opts %opts-w-format
1149 (pass-if "quiet (2 args)"
1150 (null? (call-with-warnings
1152 (compile '(format #t "~A ~A!" "hello" "world")
1153 #:opts %opts-w-format
1156 (pass-if "wrong port arg"
1157 (let ((w (call-with-warnings
1159 (compile '(format 10 "foo")
1160 #:opts %opts-w-format
1162 (and (= (length w) 1)
1163 (number? (string-contains (car w)
1164 "wrong port argument")))))
1166 (pass-if "non-literal format string"
1167 (let ((w (call-with-warnings
1169 (compile '(format #f fmt)
1170 #:opts %opts-w-format
1172 (and (= (length w) 1)
1173 (number? (string-contains (car w)
1174 "non-literal format string")))))
1176 (pass-if "non-literal format string using gettext"
1177 (null? (call-with-warnings
1179 (compile '(format #t (_ "~A ~A!") "hello" "world")
1180 #:opts %opts-w-format
1183 (pass-if "wrong format string"
1184 (let ((w (call-with-warnings
1186 (compile '(format #f 'not-a-string)
1187 #:opts %opts-w-format
1189 (and (= (length w) 1)
1190 (number? (string-contains (car w)
1191 "wrong format string")))))
1193 (pass-if "wrong number of args"
1194 (let ((w (call-with-warnings
1196 (compile '(format "shbweeb")
1197 #:opts %opts-w-format
1199 (and (= (length w) 1)
1200 (number? (string-contains (car w)
1201 "wrong number of arguments")))))
1203 (pass-if "~%, ~~, ~&, ~t, ~_, and ~\\n"
1204 (null? (call-with-warnings
1206 (compile '(format some-port "~&~3_~~ ~\n~12they~%")
1207 #:opts %opts-w-format
1210 (pass-if "one missing argument"
1211 (let ((w (call-with-warnings
1213 (compile '(format some-port "foo ~A~%")
1214 #:opts %opts-w-format
1216 (and (= (length w) 1)
1217 (number? (string-contains (car w)
1218 "expected 1, got 0")))))
1220 (pass-if "one missing argument, gettext"
1221 (let ((w (call-with-warnings
1223 (compile '(format some-port (_ "foo ~A~%"))
1224 #:opts %opts-w-format
1226 (and (= (length w) 1)
1227 (number? (string-contains (car w)
1228 "expected 1, got 0")))))
1230 (pass-if "two missing arguments"
1231 (let ((w (call-with-warnings
1233 (compile '(format #f "foo ~10,2f and bar ~S~%")
1234 #:opts %opts-w-format
1236 (and (= (length w) 1)
1237 (number? (string-contains (car w)
1238 "expected 2, got 0")))))
1240 (pass-if "one given, one missing argument"
1241 (let ((w (call-with-warnings
1243 (compile '(format #t "foo ~A and ~S~%" hey)
1244 #:opts %opts-w-format
1246 (and (= (length w) 1)
1247 (number? (string-contains (car w)
1248 "expected 2, got 1")))))
1250 (pass-if "too many arguments"
1251 (let ((w (call-with-warnings
1253 (compile '(format #t "foo ~A~%" 1 2)
1254 #:opts %opts-w-format
1256 (and (= (length w) 1)
1257 (number? (string-contains (car w)
1258 "expected 1, got 2")))))
1260 (with-test-prefix "conditionals"
1262 (null? (call-with-warnings
1264 (compile '(format #f "~A ~[foo~;bar~;baz~;~] ~10,2f"
1266 #:opts %opts-w-format
1269 (pass-if "literals with selector"
1270 (let ((w (call-with-warnings
1272 (compile '(format #f "~2[foo~;bar~;baz~;~] ~A"
1274 #:opts %opts-w-format
1276 (and (= (length w) 1)
1277 (number? (string-contains (car w)
1278 "expected 1, got 2")))))
1280 (pass-if "escapes (exact count)"
1281 (let ((w (call-with-warnings
1283 (compile '(format #f "~[~a~;~a~]")
1284 #:opts %opts-w-format
1286 (and (= (length w) 1)
1287 (number? (string-contains (car w)
1288 "expected 2, got 0")))))
1290 (pass-if "escapes with selector"
1291 (let ((w (call-with-warnings
1293 (compile '(format #f "~1[chbouib~;~a~]")
1294 #:opts %opts-w-format
1296 (and (= (length w) 1)
1297 (number? (string-contains (car w)
1298 "expected 1, got 0")))))
1300 (pass-if "escapes, range"
1301 (let ((w (call-with-warnings
1303 (compile '(format #f "~[chbouib~;~a~;~2*~a~]")
1304 #:opts %opts-w-format
1306 (and (= (length w) 1)
1307 (number? (string-contains (car w)
1308 "expected 1 to 4, got 0")))))
1311 (let ((w (call-with-warnings
1313 (compile '(format #f "~@[temperature=~d~]")
1314 #:opts %opts-w-format
1316 (and (= (length w) 1)
1317 (number? (string-contains (car w)
1318 "expected 1, got 0")))))
1321 (let ((w (call-with-warnings
1323 (compile '(format #f "~:[~[hey~;~a~;~va~]~;~3*~]")
1324 #:opts %opts-w-format
1326 (and (= (length w) 1)
1327 (number? (string-contains (car w)
1328 "expected 2 to 4, got 0")))))
1330 (pass-if "unterminated"
1331 (let ((w (call-with-warnings
1333 (compile '(format #f "~[unterminated")
1334 #:opts %opts-w-format
1336 (and (= (length w) 1)
1337 (number? (string-contains (car w)
1338 "unterminated conditional")))))
1340 (pass-if "unexpected ~;"
1341 (let ((w (call-with-warnings
1343 (compile '(format #f "foo~;bar")
1344 #:opts %opts-w-format
1346 (and (= (length w) 1)
1347 (number? (string-contains (car w)
1350 (pass-if "unexpected ~]"
1351 (let ((w (call-with-warnings
1353 (compile '(format #f "foo~]")
1354 #:opts %opts-w-format
1356 (and (= (length w) 1)
1357 (number? (string-contains (car w)
1361 (null? (call-with-warnings
1363 (compile '(format #f "~A ~{~S~} ~A"
1364 'hello '("ladies" "and")
1366 #:opts %opts-w-format
1369 (pass-if "~{...~}, too many args"
1370 (let ((w (call-with-warnings
1372 (compile '(format #f "~{~S~}" 1 2 3)
1373 #:opts %opts-w-format
1375 (and (= (length w) 1)
1376 (number? (string-contains (car w)
1377 "expected 1, got 3")))))
1380 (null? (call-with-warnings
1382 (compile '(format #f "~@{~S~}" 1 2 3)
1383 #:opts %opts-w-format
1386 (pass-if "~@{...~}, too few args"
1387 (let ((w (call-with-warnings
1389 (compile '(format #f "~A ~@{~S~}")
1390 #:opts %opts-w-format
1392 (and (= (length w) 1)
1393 (number? (string-contains (car w)
1394 "expected at least 1, got 0")))))
1396 (pass-if "unterminated ~{...~}"
1397 (let ((w (call-with-warnings
1399 (compile '(format #f "~{")
1400 #:opts %opts-w-format
1402 (and (= (length w) 1)
1403 (number? (string-contains (car w)
1407 (null? (call-with-warnings
1409 (compile '(format #f "~:@(~A ~A~)" 'foo 'bar)
1410 #:opts %opts-w-format
1414 (let ((w (call-with-warnings
1416 (compile '(format #f "~v_foo")
1417 #:opts %opts-w-format
1419 (and (= (length w) 1)
1420 (number? (string-contains (car w)
1421 "expected 1, got 0")))))
1423 (null? (call-with-warnings
1425 (compile '(format #f "~v:@y" 1 123)
1426 #:opts %opts-w-format
1431 (let ((w (call-with-warnings
1433 (compile '(format #f "~2*~a" 'a 'b)
1434 #:opts %opts-w-format
1436 (and (= (length w) 1)
1437 (number? (string-contains (car w)
1438 "expected 3, got 2")))))
1441 (null? (call-with-warnings
1443 (compile '(format #f "~?" "~d ~d" '(1 2))
1444 #:opts %opts-w-format
1447 (pass-if "complex 1"
1448 (let ((w (call-with-warnings
1450 (compile '(format #f
1451 "~4@S ~32S~@[;; ~1{~@?~}~]~@[~61t at ~a~]\n"
1453 #:opts %opts-w-format
1455 (and (= (length w) 1)
1456 (number? (string-contains (car w)
1457 "expected 4, got 6")))))
1459 (pass-if "complex 2"
1460 (let ((w (call-with-warnings
1462 (compile '(format #f
1463 "~:(~A~) Commands~:[~; [abbrev]~]:~2%"
1465 #:opts %opts-w-format
1467 (and (= (length w) 1)
1468 (number? (string-contains (car w)
1469 "expected 2, got 4")))))
1471 (pass-if "complex 3"
1472 (let ((w (call-with-warnings
1474 (compile '(format #f "~9@a~:[~*~3_~;~3d~] ~v:@y~%")
1475 #:opts %opts-w-format
1477 (and (= (length w) 1)
1478 (number? (string-contains (car w)
1479 "expected 5, got 0")))))
1481 (pass-if "ice-9 format"
1482 (let ((w (call-with-warnings
1484 (let ((in (open-input-string
1485 "(use-modules ((ice-9 format)
1486 #:renamer (symbol-prefix-proc 'i9-)))
1487 (i9-format #t \"yo! ~A\" 1 2)")))
1488 (read-and-compile in
1489 #:opts %opts-w-format
1490 #:to 'assembly))))))
1491 (and (= (length w) 1)
1492 (number? (string-contains (car w)
1493 "expected 1, got 2")))))
1495 (pass-if "not format"
1496 (null? (call-with-warnings
1498 (compile '(let ((format chbouib))
1499 (format #t "not ~A a format string"))
1500 #:opts %opts-w-format
1501 #:to 'assembly)))))))