add effect+exception-free-primitive? predicate
[bpt/guile.git] / test-suite / tests / tree-il.test
CommitLineData
ce09ee19
AW
1;;;; tree-il.test --- test suite for compiling tree-il -*- scheme -*-
2;;;; Andy Wingo <wingo@pobox.com> --- May 2009
3;;;;
a5bbb22e 4;;;; Copyright (C) 2009, 2010 Free Software Foundation, Inc.
ce09ee19
AW
5;;;;
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
53befeb7
NJ
9;;;; version 3 of the License, or (at your option) any later version.
10;;;;
ce09ee19
AW
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.
53befeb7 15;;;;
ce09ee19
AW
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
19
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)
4b856371 24 #:use-module (system base message)
ce09ee19 25 #:use-module (language tree-il)
4b856371
LC
26 #:use-module (language glil)
27 #:use-module (srfi srfi-13))
ce09ee19 28
e0c90f90
AW
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.
32
33(define (strip-source x)
34 (post-order! (lambda (x) (set! (tree-il-src x) #f))
35 x))
36
ce09ee19
AW
37(define-syntax assert-scheme->glil
38 (syntax-rules ()
39 ((_ in out)
e0c90f90
AW
40 (let ((tree-il (strip-source
41 (compile 'in #:from 'scheme #:to 'tree-il))))
ce09ee19
AW
42 (pass-if 'in
43 (equal? (unparse-glil (compile tree-il #:from 'tree-il #:to 'glil))
44 'out))))))
45
46(define-syntax assert-tree-il->glil
ce09ee19
AW
47 (syntax-rules ()
48 ((_ in pat test ...)
49 (let ((exp 'in))
50 (pass-if 'in
51 (let ((glil (unparse-glil
e0c90f90 52 (compile (strip-source (parse-tree-il exp))
ce09ee19
AW
53 #:from 'tree-il #:to 'glil))))
54 (pmatch glil
55 (pat (guard test ...) #t)
56 (else #f))))))))
57
ce09ee19
AW
58(with-test-prefix "void"
59 (assert-tree-il->glil
60 (void)
8a4ca0ea 61 (program () (std-prelude 0 0 #f) (label _) (void) (call return 1)))
ce09ee19
AW
62 (assert-tree-il->glil
63 (begin (void) (const 1))
8a4ca0ea 64 (program () (std-prelude 0 0 #f) (label _) (const 1) (call return 1)))
ce09ee19
AW
65 (assert-tree-il->glil
66 (apply (primitive +) (void) (const 1))
8a4ca0ea 67 (program () (std-prelude 0 0 #f) (label _) (void) (call add1 1) (call return 1))))
ce09ee19
AW
68
69(with-test-prefix "application"
70 (assert-tree-il->glil
71 (apply (toplevel foo) (const 1))
a5bbb22e 72 (program () (std-prelude 0 0 #f) (label _) (toplevel ref foo) (const 1) (call tail-call 1)))
8a4ca0ea 73 (assert-tree-il->glil
ce09ee19 74 (begin (apply (toplevel foo) (const 1)) (void))
8a4ca0ea 75 (program () (std-prelude 0 0 #f) (label _) (call new-frame 0) (toplevel ref foo) (const 1) (mv-call 1 ,l1)
0f423f20 76 (call drop 1) (branch br ,l2)
05c51bcf 77 (label ,l3) (mv-bind 0 #f)
0f423f20 78 (label ,l4)
30a5e062 79 (void) (call return 1))
0f423f20 80 (and (eq? l1 l3) (eq? l2 l4)))
ce09ee19
AW
81 (assert-tree-il->glil
82 (apply (toplevel foo) (apply (toplevel bar)))
8a4ca0ea 83 (program () (std-prelude 0 0 #f) (label _) (toplevel ref foo) (call new-frame 0) (toplevel ref bar) (call call 0)
a5bbb22e 84 (call tail-call 1))))
ce09ee19
AW
85
86(with-test-prefix "conditional"
8a4ca0ea 87 (assert-tree-il->glil
0e4b7818
AW
88 (if (toplevel foo) (const 1) (const 2))
89 (program () (std-prelude 0 0 #f) (label _) (toplevel ref foo) (branch br-if-not ,l1)
ce09ee19
AW
90 (const 1) (call return 1)
91 (label ,l2) (const 2) (call return 1))
92 (eq? l1 l2))
93
8a4ca0ea 94 (assert-tree-il->glil
0e4b7818
AW
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)
ce09ee19
AW
97 (label ,l3) (label ,l4) (const #f) (call return 1))
98 (eq? l1 l3) (eq? l2 l4))
99
8a4ca0ea 100 (assert-tree-il->glil
0e4b7818
AW
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)
ce09ee19
AW
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)))
107
108(with-test-prefix "primitive-ref"
109 (assert-tree-il->glil
110 (primitive +)
8a4ca0ea 111 (program () (std-prelude 0 0 #f) (label _) (toplevel ref +) (call return 1)))
ce09ee19
AW
112
113 (assert-tree-il->glil
114 (begin (primitive +) (const #f))
8a4ca0ea 115 (program () (std-prelude 0 0 #f) (label _) (const #f) (call return 1)))
ce09ee19
AW
116
117 (assert-tree-il->glil
118 (apply (primitive null?) (primitive +))
8a4ca0ea 119 (program () (std-prelude 0 0 #f) (label _) (toplevel ref +) (call null? 1)
ce09ee19
AW
120 (call return 1))))
121
122(with-test-prefix "lexical refs"
123 (assert-tree-il->glil
124 (let (x) (y) ((const 1)) (lexical x y))
8a4ca0ea 125 (program () (std-prelude 0 1 #f) (label _)
66d3e9a3
AW
126 (const 1) (bind (x #f 0)) (lexical #t #f set 0)
127 (lexical #t #f ref 0) (call return 1)
ce09ee19
AW
128 (unbind)))
129
130 (assert-tree-il->glil
131 (let (x) (y) ((const 1)) (begin (lexical x y) (const #f)))
8a4ca0ea 132 (program () (std-prelude 0 1 #f) (label _)
66d3e9a3 133 (const 1) (bind (x #f 0)) (lexical #t #f set 0)
ce09ee19
AW
134 (const #f) (call return 1)
135 (unbind)))
136
137 (assert-tree-il->glil
138 (let (x) (y) ((const 1)) (apply (primitive null?) (lexical x y)))
8a4ca0ea 139 (program () (std-prelude 0 1 #f) (label _)
66d3e9a3
AW
140 (const 1) (bind (x #f 0)) (lexical #t #f set 0)
141 (lexical #t #f ref 0) (call null? 1) (call return 1)
ce09ee19
AW
142 (unbind))))
143
144(with-test-prefix "lexical sets"
145 (assert-tree-il->glil
aaae0d5a
AW
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))))
8a4ca0ea 149 (program () (std-prelude 0 1 #f) (label _)
66d3e9a3 150 (const 1) (bind (x #t 0)) (lexical #t #t box 0)
aaae0d5a
AW
151 (lexical #t #t ref 0) (call add1 1) (lexical #t #t set 0)
152 (void) (call return 1)
ce09ee19
AW
153 (unbind)))
154
155 (assert-tree-il->glil
aaae0d5a
AW
156 (let (x) (y) ((const 1))
157 (begin (set! (lexical x y) (apply (primitive 1+) (lexical x y)))
158 (lexical x y)))
8a4ca0ea 159 (program () (std-prelude 0 1 #f) (label _)
66d3e9a3 160 (const 1) (bind (x #t 0)) (lexical #t #t box 0)
aaae0d5a
AW
161 (lexical #t #t ref 0) (call add1 1) (lexical #t #t set 0)
162 (lexical #t #t ref 0) (call return 1)
ce09ee19
AW
163 (unbind)))
164
165 (assert-tree-il->glil
166 (let (x) (y) ((const 1))
aaae0d5a
AW
167 (apply (primitive null?)
168 (set! (lexical x y) (apply (primitive 1+) (lexical x y)))))
8a4ca0ea 169 (program () (std-prelude 0 1 #f) (label _)
66d3e9a3 170 (const 1) (bind (x #t 0)) (lexical #t #t box 0)
aaae0d5a
AW
171 (lexical #t #t ref 0) (call add1 1) (lexical #t #t set 0) (void)
172 (call null? 1) (call return 1)
ce09ee19
AW
173 (unbind))))
174
175(with-test-prefix "module refs"
176 (assert-tree-il->glil
177 (@ (foo) bar)
8a4ca0ea 178 (program () (std-prelude 0 0 #f) (label _)
ce09ee19
AW
179 (module public ref (foo) bar)
180 (call return 1)))
181
182 (assert-tree-il->glil
183 (begin (@ (foo) bar) (const #f))
8a4ca0ea 184 (program () (std-prelude 0 0 #f) (label _)
ce09ee19
AW
185 (module public ref (foo) bar) (call drop 1)
186 (const #f) (call return 1)))
187
188 (assert-tree-il->glil
189 (apply (primitive null?) (@ (foo) bar))
8a4ca0ea 190 (program () (std-prelude 0 0 #f) (label _)
ce09ee19
AW
191 (module public ref (foo) bar)
192 (call null? 1) (call return 1)))
193
194 (assert-tree-il->glil
195 (@@ (foo) bar)
8a4ca0ea 196 (program () (std-prelude 0 0 #f) (label _)
ce09ee19
AW
197 (module private ref (foo) bar)
198 (call return 1)))
199
200 (assert-tree-il->glil
201 (begin (@@ (foo) bar) (const #f))
8a4ca0ea 202 (program () (std-prelude 0 0 #f) (label _)
ce09ee19
AW
203 (module private ref (foo) bar) (call drop 1)
204 (const #f) (call return 1)))
205
206 (assert-tree-il->glil
207 (apply (primitive null?) (@@ (foo) bar))
8a4ca0ea 208 (program () (std-prelude 0 0 #f) (label _)
ce09ee19
AW
209 (module private ref (foo) bar)
210 (call null? 1) (call return 1))))
211
212(with-test-prefix "module sets"
213 (assert-tree-il->glil
214 (set! (@ (foo) bar) (const 2))
8a4ca0ea 215 (program () (std-prelude 0 0 #f) (label _)
ce09ee19
AW
216 (const 2) (module public set (foo) bar)
217 (void) (call return 1)))
218
219 (assert-tree-il->glil
220 (begin (set! (@ (foo) bar) (const 2)) (const #f))
8a4ca0ea 221 (program () (std-prelude 0 0 #f) (label _)
ce09ee19
AW
222 (const 2) (module public set (foo) bar)
223 (const #f) (call return 1)))
224
225 (assert-tree-il->glil
226 (apply (primitive null?) (set! (@ (foo) bar) (const 2)))
8a4ca0ea 227 (program () (std-prelude 0 0 #f) (label _)
ce09ee19
AW
228 (const 2) (module public set (foo) bar)
229 (void) (call null? 1) (call return 1)))
230
231 (assert-tree-il->glil
232 (set! (@@ (foo) bar) (const 2))
8a4ca0ea 233 (program () (std-prelude 0 0 #f) (label _)
ce09ee19
AW
234 (const 2) (module private set (foo) bar)
235 (void) (call return 1)))
236
237 (assert-tree-il->glil
238 (begin (set! (@@ (foo) bar) (const 2)) (const #f))
8a4ca0ea 239 (program () (std-prelude 0 0 #f) (label _)
ce09ee19
AW
240 (const 2) (module private set (foo) bar)
241 (const #f) (call return 1)))
242
243 (assert-tree-il->glil
244 (apply (primitive null?) (set! (@@ (foo) bar) (const 2)))
8a4ca0ea 245 (program () (std-prelude 0 0 #f) (label _)
ce09ee19
AW
246 (const 2) (module private set (foo) bar)
247 (void) (call null? 1) (call return 1))))
248
249(with-test-prefix "toplevel refs"
250 (assert-tree-il->glil
251 (toplevel bar)
8a4ca0ea 252 (program () (std-prelude 0 0 #f) (label _)
ce09ee19
AW
253 (toplevel ref bar)
254 (call return 1)))
255
256 (assert-tree-il->glil
257 (begin (toplevel bar) (const #f))
8a4ca0ea 258 (program () (std-prelude 0 0 #f) (label _)
ce09ee19
AW
259 (toplevel ref bar) (call drop 1)
260 (const #f) (call return 1)))
261
262 (assert-tree-il->glil
263 (apply (primitive null?) (toplevel bar))
8a4ca0ea 264 (program () (std-prelude 0 0 #f) (label _)
ce09ee19
AW
265 (toplevel ref bar)
266 (call null? 1) (call return 1))))
267
268(with-test-prefix "toplevel sets"
269 (assert-tree-il->glil
270 (set! (toplevel bar) (const 2))
8a4ca0ea 271 (program () (std-prelude 0 0 #f) (label _)
ce09ee19
AW
272 (const 2) (toplevel set bar)
273 (void) (call return 1)))
274
275 (assert-tree-il->glil
276 (begin (set! (toplevel bar) (const 2)) (const #f))
8a4ca0ea 277 (program () (std-prelude 0 0 #f) (label _)
ce09ee19
AW
278 (const 2) (toplevel set bar)
279 (const #f) (call return 1)))
280
281 (assert-tree-il->glil
282 (apply (primitive null?) (set! (toplevel bar) (const 2)))
8a4ca0ea 283 (program () (std-prelude 0 0 #f) (label _)
ce09ee19
AW
284 (const 2) (toplevel set bar)
285 (void) (call null? 1) (call return 1))))
286
287(with-test-prefix "toplevel defines"
288 (assert-tree-il->glil
289 (define bar (const 2))
8a4ca0ea 290 (program () (std-prelude 0 0 #f) (label _)
ce09ee19
AW
291 (const 2) (toplevel define bar)
292 (void) (call return 1)))
293
294 (assert-tree-il->glil
295 (begin (define bar (const 2)) (const #f))
8a4ca0ea 296 (program () (std-prelude 0 0 #f) (label _)
ce09ee19
AW
297 (const 2) (toplevel define bar)
298 (const #f) (call return 1)))
299
300 (assert-tree-il->glil
301 (apply (primitive null?) (define bar (const 2)))
8a4ca0ea 302 (program () (std-prelude 0 0 #f) (label _)
ce09ee19
AW
303 (const 2) (toplevel define bar)
304 (void) (call null? 1) (call return 1))))
305
306(with-test-prefix "constants"
307 (assert-tree-il->glil
308 (const 2)
8a4ca0ea 309 (program () (std-prelude 0 0 #f) (label _)
ce09ee19
AW
310 (const 2) (call return 1)))
311
312 (assert-tree-il->glil
313 (begin (const 2) (const #f))
8a4ca0ea 314 (program () (std-prelude 0 0 #f) (label _)
ce09ee19
AW
315 (const #f) (call return 1)))
316
317 (assert-tree-il->glil
318 (apply (primitive null?) (const 2))
8a4ca0ea 319 (program () (std-prelude 0 0 #f) (label _)
ce09ee19
AW
320 (const 2) (call null? 1) (call return 1))))
321
322(with-test-prefix "lambda"
323 (assert-tree-il->glil
8a4ca0ea 324 (lambda ()
1e2a8edb 325 (lambda-case (((x) #f #f #f () (y)) (const 2)) #f))
8a4ca0ea 326 (program () (std-prelude 0 0 #f) (label _)
258344b4 327 (program () (std-prelude 1 1 #f)
8a4ca0ea
AW
328 (bind (x #f 0)) (label _)
329 (const 2) (call return 1) (unbind))
ce09ee19
AW
330 (call return 1)))
331
332 (assert-tree-il->glil
8a4ca0ea 333 (lambda ()
1e2a8edb 334 (lambda-case (((x y) #f #f #f () (x1 y1))
8a4ca0ea
AW
335 (const 2))
336 #f))
337 (program () (std-prelude 0 0 #f) (label _)
258344b4 338 (program () (std-prelude 2 2 #f)
8a4ca0ea
AW
339 (bind (x #f 0) (y #f 1)) (label _)
340 (const 2) (call return 1)
341 (unbind))
ce09ee19
AW
342 (call return 1)))
343
344 (assert-tree-il->glil
8a4ca0ea 345 (lambda ()
1e2a8edb 346 (lambda-case ((() #f x #f () (y)) (const 2))
8a4ca0ea
AW
347 #f))
348 (program () (std-prelude 0 0 #f) (label _)
899d37a6 349 (program () (opt-prelude 0 0 0 1 #f)
8a4ca0ea
AW
350 (bind (x #f 0)) (label _)
351 (const 2) (call return 1)
352 (unbind))
ce09ee19
AW
353 (call return 1)))
354
355 (assert-tree-il->glil
8a4ca0ea 356 (lambda ()
1e2a8edb 357 (lambda-case (((x) #f x1 #f () (y y1)) (const 2))
8a4ca0ea
AW
358 #f))
359 (program () (std-prelude 0 0 #f) (label _)
899d37a6 360 (program () (opt-prelude 1 0 1 2 #f)
8a4ca0ea
AW
361 (bind (x #f 0) (x1 #f 1)) (label _)
362 (const 2) (call return 1)
363 (unbind))
ce09ee19
AW
364 (call return 1)))
365
366 (assert-tree-il->glil
8a4ca0ea 367 (lambda ()
1e2a8edb 368 (lambda-case (((x) #f x1 #f () (y y1)) (lexical x y))
8a4ca0ea
AW
369 #f))
370 (program () (std-prelude 0 0 #f) (label _)
899d37a6 371 (program () (opt-prelude 1 0 1 2 #f)
8a4ca0ea
AW
372 (bind (x #f 0) (x1 #f 1)) (label _)
373 (lexical #t #f ref 0) (call return 1)
374 (unbind))
ce09ee19
AW
375 (call return 1)))
376
377 (assert-tree-il->glil
8a4ca0ea 378 (lambda ()
1e2a8edb 379 (lambda-case (((x) #f x1 #f () (y y1)) (lexical x1 y1))
8a4ca0ea
AW
380 #f))
381 (program () (std-prelude 0 0 #f) (label _)
899d37a6 382 (program () (opt-prelude 1 0 1 2 #f)
8a4ca0ea
AW
383 (bind (x #f 0) (x1 #f 1)) (label _)
384 (lexical #t #f ref 1) (call return 1)
385 (unbind))
a1a482e0
AW
386 (call return 1)))
387
388 (assert-tree-il->glil
8a4ca0ea 389 (lambda ()
1e2a8edb 390 (lambda-case (((x) #f #f #f () (x1))
8a4ca0ea 391 (lambda ()
1e2a8edb 392 (lambda-case (((y) #f #f #f () (y1))
8a4ca0ea
AW
393 (lexical x x1))
394 #f)))
395 #f))
396 (program () (std-prelude 0 0 #f) (label _)
397 (program () (std-prelude 1 1 #f)
398 (bind (x #f 0)) (label _)
258344b4 399 (program () (std-prelude 1 1 #f)
8a4ca0ea
AW
400 (bind (y #f 0)) (label _)
401 (lexical #f #f ref 0) (call return 1)
402 (unbind))
66d3e9a3 403 (lexical #t #f ref 0)
6f16379e 404 (call make-closure 1)
8a4ca0ea
AW
405 (call return 1)
406 (unbind))
ce09ee19
AW
407 (call return 1))))
408
409(with-test-prefix "sequence"
410 (assert-tree-il->glil
411 (begin (begin (const 2) (const #f)) (const #t))
8a4ca0ea 412 (program () (std-prelude 0 0 #f) (label _)
ce09ee19
AW
413 (const #t) (call return 1)))
414
415 (assert-tree-il->glil
416 (apply (primitive null?) (begin (const #f) (const 2)))
8a4ca0ea 417 (program () (std-prelude 0 0 #f) (label _)
ce09ee19 418 (const 2) (call null? 1) (call return 1))))
5af166bd
AW
419
420;; FIXME: binding info for or-hacked locals might bork the disassembler,
421;; and could be tightened in any case
422(with-test-prefix "the or hack"
8a4ca0ea 423 (assert-tree-il->glil
5af166bd
AW
424 (let (x) (y) ((const 1))
425 (if (lexical x y)
426 (lexical x y)
427 (let (a) (b) ((const 2))
428 (lexical a b))))
8a4ca0ea 429 (program () (std-prelude 0 1 #f) (label _)
66d3e9a3
AW
430 (const 1) (bind (x #f 0)) (lexical #t #f set 0)
431 (lexical #t #f ref 0) (branch br-if-not ,l1)
432 (lexical #t #f ref 0) (call return 1)
5af166bd 433 (label ,l2)
66d3e9a3
AW
434 (const 2) (bind (a #f 0)) (lexical #t #f set 0)
435 (lexical #t #f ref 0) (call return 1)
5af166bd
AW
436 (unbind)
437 (unbind))
438 (eq? l1 l2))
439
aaae0d5a 440 ;; second bound var is unreferenced
8a4ca0ea 441 (assert-tree-il->glil
5af166bd
AW
442 (let (x) (y) ((const 1))
443 (if (lexical x y)
444 (lexical x y)
445 (let (a) (b) ((const 2))
446 (lexical x y))))
8a4ca0ea 447 (program () (std-prelude 0 1 #f) (label _)
66d3e9a3
AW
448 (const 1) (bind (x #f 0)) (lexical #t #f set 0)
449 (lexical #t #f ref 0) (branch br-if-not ,l1)
450 (lexical #t #f ref 0) (call return 1)
5af166bd 451 (label ,l2)
66d3e9a3 452 (lexical #t #f ref 0) (call return 1)
5af166bd
AW
453 (unbind))
454 (eq? l1 l2)))
0f423f20
AW
455
456(with-test-prefix "apply"
457 (assert-tree-il->glil
458 (apply (primitive @apply) (toplevel foo) (toplevel bar))
a5bbb22e 459 (program () (std-prelude 0 0 #f) (label _) (toplevel ref foo) (toplevel ref bar) (call tail-apply 2)))
8a4ca0ea 460 (assert-tree-il->glil
0f423f20 461 (begin (apply (primitive @apply) (toplevel foo) (toplevel bar)) (void))
8a4ca0ea 462 (program () (std-prelude 0 0 #f) (label _)
b7946e9e 463 (call new-frame 0) (toplevel ref apply) (toplevel ref foo) (toplevel ref bar) (mv-call 2 ,l1)
05c51bcf 464 (call drop 1) (branch br ,l2) (label ,l3) (mv-bind 0 #f)
0f423f20
AW
465 (label ,l4)
466 (void) (call return 1))
467 (and (eq? l1 l3) (eq? l2 l4)))
468 (assert-tree-il->glil
469 (apply (toplevel foo) (apply (toplevel @apply) (toplevel bar) (toplevel baz)))
8a4ca0ea 470 (program () (std-prelude 0 0 #f) (label _)
0f423f20 471 (toplevel ref foo)
b7946e9e 472 (call new-frame 0) (toplevel ref bar) (toplevel ref baz) (call apply 2)
a5bbb22e 473 (call tail-call 1))))
0f423f20
AW
474
475(with-test-prefix "call/cc"
476 (assert-tree-il->glil
477 (apply (primitive @call-with-current-continuation) (toplevel foo))
a5bbb22e 478 (program () (std-prelude 0 0 #f) (label _) (toplevel ref foo) (call tail-call/cc 1)))
8a4ca0ea 479 (assert-tree-il->glil
0f423f20 480 (begin (apply (primitive @call-with-current-continuation) (toplevel foo)) (void))
8a4ca0ea 481 (program () (std-prelude 0 0 #f) (label _)
b7946e9e 482 (call new-frame 0) (toplevel ref call-with-current-continuation) (toplevel ref foo) (mv-call 1 ,l1)
05c51bcf 483 (call drop 1) (branch br ,l2) (label ,l3) (mv-bind 0 #f)
0f423f20
AW
484 (label ,l4)
485 (void) (call return 1))
486 (and (eq? l1 l3) (eq? l2 l4)))
487 (assert-tree-il->glil
488 (apply (toplevel foo)
489 (apply (toplevel @call-with-current-continuation) (toplevel bar)))
8a4ca0ea 490 (program () (std-prelude 0 0 #f) (label _)
0f423f20
AW
491 (toplevel ref foo)
492 (toplevel ref bar) (call call/cc 1)
a5bbb22e 493 (call tail-call 1))))
0f423f20 494
f4aa0f10
LC
495\f
496(with-test-prefix "tree-il-fold"
497
498 (pass-if "empty tree"
499 (let ((leaf? #f) (up? #f) (down? #f) (mark (list 'mark)))
500 (and (eq? mark
501 (tree-il-fold (lambda (x y) (set! leaf? #t) y)
502 (lambda (x y) (set! down? #t) y)
503 (lambda (x y) (set! up? #t) y)
504 mark
505 '()))
506 (not leaf?)
507 (not up?)
508 (not down?))))
509
510 (pass-if "lambda and application"
511 (let* ((leaves '()) (ups '()) (downs '())
512 (result (tree-il-fold (lambda (x y)
513 (set! leaves (cons x leaves))
514 (1+ y))
515 (lambda (x y)
516 (set! downs (cons x downs))
517 (1+ y))
518 (lambda (x y)
519 (set! ups (cons x ups))
520 (1+ y))
521 0
522 (parse-tree-il
8a4ca0ea
AW
523 '(lambda ()
524 (lambda-case
1e2a8edb 525 (((x y) #f #f #f () (x1 y1))
8a4ca0ea
AW
526 (apply (toplevel +)
527 (lexical x x1)
528 (lexical y y1)))
529 #f))))))
f4aa0f10
LC
530 (and (equal? (map strip-source leaves)
531 (list (make-lexical-ref #f 'y 'y1)
532 (make-lexical-ref #f 'x 'x1)
533 (make-toplevel-ref #f '+)))
8a4ca0ea 534 (= (length downs) 3)
f4aa0f10
LC
535 (equal? (reverse (map strip-source ups))
536 (map strip-source downs))))))
4b856371
LC
537
538\f
539;;;
540;;; Warnings.
541;;;
542
543;; Make sure we get English messages.
544(setlocale LC_ALL "C")
545
546(define (call-with-warnings thunk)
547 (let ((port (open-output-string)))
548 (with-fluid* *current-warning-port* port
549 thunk)
550 (let ((warnings (get-output-string port)))
551 (string-tokenize warnings
552 (char-set-complement (char-set #\newline))))))
553
554(define %opts-w-unused
555 '(#:warnings (unused-variable)))
556
bcae9a98
LC
557(define %opts-w-unused-toplevel
558 '(#:warnings (unused-toplevel)))
559
f67ddf9d
LC
560(define %opts-w-unbound
561 '(#:warnings (unbound-variable)))
4b856371 562
ae03cf1f
LC
563(define %opts-w-arity
564 '(#:warnings (arity-mismatch)))
565
566
4b856371
LC
567(with-test-prefix "warnings"
568
569 (pass-if "unknown warning type"
570 (let ((w (call-with-warnings
571 (lambda ()
572 (compile #t #:opts '(#:warnings (does-not-exist)))))))
573 (and (= (length w) 1)
574 (number? (string-contains (car w) "unknown warning")))))
575
576 (with-test-prefix "unused-variable"
577
578 (pass-if "quiet"
579 (null? (call-with-warnings
580 (lambda ()
581 (compile '(lambda (x y) (+ x y))
582 #:opts %opts-w-unused)))))
583
584 (pass-if "let/unused"
585 (let ((w (call-with-warnings
586 (lambda ()
587 (compile '(lambda (x)
588 (let ((y (+ x 2)))
589 x))
590 #:opts %opts-w-unused)))))
591 (and (= (length w) 1)
592 (number? (string-contains (car w) "unused variable `y'")))))
593
594 (pass-if "shadowed variable"
595 (let ((w (call-with-warnings
596 (lambda ()
597 (compile '(lambda (x)
598 (let ((y x))
599 (let ((y (+ x 2)))
600 (+ x y))))
601 #:opts %opts-w-unused)))))
602 (and (= (length w) 1)
603 (number? (string-contains (car w) "unused variable `y'")))))
604
605 (pass-if "letrec"
606 (null? (call-with-warnings
607 (lambda ()
608 (compile '(lambda ()
609 (letrec ((x (lambda () (y)))
610 (y (lambda () (x))))
611 y))
612 #:opts %opts-w-unused)))))
613
614 (pass-if "unused argument"
615 ;; Unused arguments should not be reported.
616 (null? (call-with-warnings
617 (lambda ()
618 (compile '(lambda (x y z) #t)
f67ddf9d
LC
619 #:opts %opts-w-unused))))))
620
bcae9a98
LC
621 (with-test-prefix "unused-toplevel"
622
623 (pass-if "used after definition"
624 (null? (call-with-warnings
625 (lambda ()
626 (let ((in (open-input-string
627 "(define foo 2) foo")))
628 (read-and-compile in
629 #:to 'assembly
630 #:opts %opts-w-unused-toplevel))))))
631
632 (pass-if "used before definition"
633 (null? (call-with-warnings
634 (lambda ()
635 (let ((in (open-input-string
636 "(define (bar) foo) (define foo 2) (bar)")))
637 (read-and-compile in
638 #:to 'assembly
639 #:opts %opts-w-unused-toplevel))))))
640
641 (pass-if "unused but public"
642 (let ((in (open-input-string
643 "(define-module (test-suite tree-il x) #:export (bar))
644 (define (bar) #t)")))
645 (null? (call-with-warnings
646 (lambda ()
647 (read-and-compile in
648 #:to 'assembly
649 #:opts %opts-w-unused-toplevel))))))
650
651 (pass-if "unused but public (more)"
652 (let ((in (open-input-string
653 "(define-module (test-suite tree-il x) #:export (bar))
654 (define (bar) (baz))
655 (define (baz) (foo))
656 (define (foo) #t)")))
657 (null? (call-with-warnings
658 (lambda ()
659 (read-and-compile in
660 #:to 'assembly
661 #:opts %opts-w-unused-toplevel))))))
662
663 (pass-if "unused but define-public"
bcae9a98
LC
664 (null? (call-with-warnings
665 (lambda ()
666 (compile '(define-public foo 2)
667 #:to 'assembly
668 #:opts %opts-w-unused-toplevel)))))
669
670 (pass-if "used by macro"
671 ;; FIXME: See comment about macros at `unused-toplevel-analysis'.
672 (throw 'unresolved)
673
674 (null? (call-with-warnings
675 (lambda ()
676 (let ((in (open-input-string
677 "(define (bar) 'foo)
678 (define-syntax baz
679 (syntax-rules () ((_) (bar))))")))
680 (read-and-compile in
681 #:to 'assembly
682 #:opts %opts-w-unused-toplevel))))))
683
684 (pass-if "unused"
685 (let ((w (call-with-warnings
686 (lambda ()
687 (compile '(define foo 2)
688 #:to 'assembly
689 #:opts %opts-w-unused-toplevel)))))
690 (and (= (length w) 1)
691 (number? (string-contains (car w)
692 (format #f "top-level variable `~A'"
693 'foo))))))
694
695 (pass-if "unused recursive"
696 (let ((w (call-with-warnings
697 (lambda ()
698 (compile '(define (foo) (foo))
699 #:to 'assembly
700 #:opts %opts-w-unused-toplevel)))))
701 (and (= (length w) 1)
702 (number? (string-contains (car w)
703 (format #f "top-level variable `~A'"
704 'foo))))))
705
706 (pass-if "unused mutually recursive"
707 (let* ((in (open-input-string
708 "(define (foo) (bar)) (define (bar) (foo))"))
709 (w (call-with-warnings
710 (lambda ()
711 (read-and-compile in
712 #:to 'assembly
713 #:opts %opts-w-unused-toplevel)))))
714 (and (= (length w) 2)
715 (number? (string-contains (car w)
716 (format #f "top-level variable `~A'"
717 'foo)))
718 (number? (string-contains (cadr w)
719 (format #f "top-level variable `~A'"
720 'bar)))))))
721
f67ddf9d
LC
722 (with-test-prefix "unbound variable"
723
724 (pass-if "quiet"
725 (null? (call-with-warnings
726 (lambda ()
727 (compile '+ #:opts %opts-w-unbound)))))
728
729 (pass-if "ref"
730 (let* ((v (gensym))
731 (w (call-with-warnings
732 (lambda ()
733 (compile v
734 #:to 'assembly
735 #:opts %opts-w-unbound)))))
736 (and (= (length w) 1)
737 (number? (string-contains (car w)
738 (format #f "unbound variable `~A'"
739 v))))))
740
741 (pass-if "set!"
742 (let* ((v (gensym))
743 (w (call-with-warnings
744 (lambda ()
745 (compile `(set! ,v 7)
746 #:to 'assembly
747 #:opts %opts-w-unbound)))))
748 (and (= (length w) 1)
749 (number? (string-contains (car w)
750 (format #f "unbound variable `~A'"
751 v))))))
752
753 (pass-if "module-local top-level is visible"
754 (let ((m (make-module))
755 (v (gensym)))
756 (beautify-user-module! m)
757 (compile `(define ,v 123)
758 #:env m #:opts %opts-w-unbound)
759 (null? (call-with-warnings
760 (lambda ()
761 (compile v
762 #:env m
763 #:to 'assembly
764 #:opts %opts-w-unbound))))))
765
766 (pass-if "module-local top-level is visible after"
767 (let ((m (make-module))
768 (v (gensym)))
769 (beautify-user-module! m)
770 (null? (call-with-warnings
771 (lambda ()
772 (let ((in (open-input-string
773 "(define (f)
774 (set! chbouib 3))
775 (define chbouib 5)")))
b6d2306d
LC
776 (read-and-compile in
777 #:env m
778 #:opts %opts-w-unbound)))))))
779
bd36e901
LC
780 (pass-if "optional arguments are visible"
781 (null? (call-with-warnings
782 (lambda ()
783 (compile '(lambda* (x #:optional y z) (list x y z))
784 #:opts %opts-w-unbound
785 #:to 'assembly)))))
786
787 (pass-if "keyword arguments are visible"
788 (null? (call-with-warnings
789 (lambda ()
790 (compile '(lambda* (x #:key y z) (list x y z))
791 #:opts %opts-w-unbound
792 #:to 'assembly)))))
793
b6d2306d
LC
794 (pass-if "GOOPS definitions are visible"
795 (let ((m (make-module))
796 (v (gensym)))
797 (beautify-user-module! m)
798 (module-use! m (resolve-interface '(oop goops)))
799 (null? (call-with-warnings
800 (lambda ()
801 (let ((in (open-input-string
802 "(define-class <foo> ()
803 (bar #:getter foo-bar))
804 (define z (foo-bar (make <foo>)))")))
f67ddf9d
LC
805 (read-and-compile in
806 #:env m
ae03cf1f
LC
807 #:opts %opts-w-unbound))))))))
808
809 (with-test-prefix "arity mismatch"
810
811 (pass-if "quiet"
812 (null? (call-with-warnings
813 (lambda ()
814 (compile '(cons 'a 'b) #:opts %opts-w-arity)))))
815
816 (pass-if "direct application"
817 (let ((w (call-with-warnings
818 (lambda ()
819 (compile '((lambda (x y) (or x y)) 1 2 3 4 5)
820 #:opts %opts-w-arity
821 #:to 'assembly)))))
822 (and (= (length w) 1)
823 (number? (string-contains (car w)
824 "wrong number of arguments to")))))
825 (pass-if "local"
826 (let ((w (call-with-warnings
827 (lambda ()
828 (compile '(let ((f (lambda (x y) (+ x y))))
829 (f 2))
830 #:opts %opts-w-arity
831 #:to 'assembly)))))
832 (and (= (length w) 1)
833 (number? (string-contains (car w)
834 "wrong number of arguments to")))))
835
836 (pass-if "global"
837 (let ((w (call-with-warnings
838 (lambda ()
839 (compile '(cons 1 2 3 4)
840 #:opts %opts-w-arity
841 #:to 'assembly)))))
842 (and (= (length w) 1)
843 (number? (string-contains (car w)
844 "wrong number of arguments to")))))
845
846 (pass-if "alias to global"
847 (let ((w (call-with-warnings
848 (lambda ()
849 (compile '(let ((f cons)) (f 1 2 3 4))
850 #:opts %opts-w-arity
851 #:to 'assembly)))))
852 (and (= (length w) 1)
853 (number? (string-contains (car w)
854 "wrong number of arguments to")))))
855
856 (pass-if "alias to lexical to global"
857 (let ((w (call-with-warnings
858 (lambda ()
859 (compile '(let ((f number?))
860 (let ((g f))
861 (f 1 2 3 4)))
862 #:opts %opts-w-arity
863 #:to 'assembly)))))
864 (and (= (length w) 1)
865 (number? (string-contains (car w)
866 "wrong number of arguments to")))))
867
868 (pass-if "alias to lexical"
869 (let ((w (call-with-warnings
870 (lambda ()
871 (compile '(let ((f (lambda (x y z) (+ x y z))))
872 (let ((g f))
873 (g 1)))
874 #:opts %opts-w-arity
875 #:to 'assembly)))))
876 (and (= (length w) 1)
877 (number? (string-contains (car w)
878 "wrong number of arguments to")))))
879
880 (pass-if "letrec"
881 (let ((w (call-with-warnings
882 (lambda ()
883 (compile '(letrec ((odd? (lambda (x) (even? (1- x))))
884 (even? (lambda (x)
885 (or (= 0 x)
886 (odd?)))))
887 (odd? 1))
888 #:opts %opts-w-arity
889 #:to 'assembly)))))
890 (and (= (length w) 1)
891 (number? (string-contains (car w)
892 "wrong number of arguments to")))))
893
99480e11
LC
894 (pass-if "case-lambda"
895 (null? (call-with-warnings
896 (lambda ()
897 (compile '(let ((f (case-lambda
898 ((x) 1)
899 ((x y) 2)
900 ((x y z) 3))))
901 (list (f 1)
902 (f 1 2)
903 (f 1 2 3)))
904 #:opts %opts-w-arity
905 #:to 'assembly)))))
906
907 (pass-if "case-lambda with wrong number of arguments"
908 (let ((w (call-with-warnings
909 (lambda ()
910 (compile '(let ((f (case-lambda
911 ((x) 1)
912 ((x y) 2))))
913 (f 1 2 3))
914 #:opts %opts-w-arity
915 #:to 'assembly)))))
916 (and (= (length w) 1)
917 (number? (string-contains (car w)
918 "wrong number of arguments to")))))
919
920 (pass-if "case-lambda*"
921 (null? (call-with-warnings
922 (lambda ()
923 (compile '(let ((f (case-lambda*
924 ((x #:optional y) 1)
925 ((x #:key y) 2)
926 ((x y #:key z) 3))))
927 (list (f 1)
928 (f 1 2)
929 (f #:y 2)
930 (f 1 2 #:z 3)))
931 #:opts %opts-w-arity
932 #:to 'assembly)))))
933
934 (pass-if "case-lambda* with wrong arguments"
935 (let ((w (call-with-warnings
936 (lambda ()
937 (compile '(let ((f (case-lambda*
938 ((x #:optional y) 1)
939 ((x #:key y) 2)
940 ((x y #:key z) 3))))
941 (list (f)
942 (f 1 #:z 3)))
943 #:opts %opts-w-arity
944 #:to 'assembly)))))
945 (and (= (length w) 2)
946 (null? (filter (lambda (w)
947 (not
948 (number?
949 (string-contains
950 w "wrong number of arguments to"))))
951 w)))))
952
ae03cf1f
LC
953 (pass-if "local toplevel-defines"
954 (let ((w (call-with-warnings
955 (lambda ()
956 (let ((in (open-input-string "
957 (define (g x) (f x))
958 (define (f) 1)")))
959 (read-and-compile in
960 #:opts %opts-w-arity
961 #:to 'assembly))))))
962 (and (= (length w) 1)
963 (number? (string-contains (car w)
964 "wrong number of arguments to")))))
965
966 (pass-if "global toplevel alias"
967 (let ((w (call-with-warnings
968 (lambda ()
969 (let ((in (open-input-string "
970 (define f cons)
971 (define (g) (f))")))
972 (read-and-compile in
973 #:opts %opts-w-arity
974 #:to 'assembly))))))
975 (and (= (length w) 1)
976 (number? (string-contains (car w)
977 "wrong number of arguments to")))))
978
979 (pass-if "local toplevel overrides global"
980 (null? (call-with-warnings
981 (lambda ()
982 (let ((in (open-input-string "
983 (define (cons) 0)
984 (define (foo x) (cons))")))
985 (read-and-compile in
986 #:opts %opts-w-arity
af5ed549
LC
987 #:to 'assembly))))))
988
989 (pass-if "keyword not passed and quiet"
990 (null? (call-with-warnings
991 (lambda ()
992 (compile '(let ((f (lambda* (x #:key y) y)))
993 (f 2))
994 #:opts %opts-w-arity
995 #:to 'assembly)))))
996
997 (pass-if "keyword passed and quiet"
998 (null? (call-with-warnings
999 (lambda ()
1000 (compile '(let ((f (lambda* (x #:key y) y)))
1001 (f 2 #:y 3))
1002 #:opts %opts-w-arity
1003 #:to 'assembly)))))
1004
1005 (pass-if "keyword passed to global and quiet"
1006 (null? (call-with-warnings
1007 (lambda ()
1008 (let ((in (open-input-string "
1009 (use-modules (system base compile))
1010 (compile '(+ 2 3) #:env (current-module))")))
1011 (read-and-compile in
1012 #:opts %opts-w-arity
1013 #:to 'assembly))))))
1014
1015 (pass-if "extra keyword"
1016 (let ((w (call-with-warnings
1017 (lambda ()
1018 (compile '(let ((f (lambda* (x #:key y) y)))
1019 (f 2 #:Z 3))
1020 #:opts %opts-w-arity
1021 #:to 'assembly)))))
1022 (and (= (length w) 1)
1023 (number? (string-contains (car w)
1024 "wrong number of arguments to")))))
1025
1026 (pass-if "extra keywords allowed"
1027 (null? (call-with-warnings
1028 (lambda ()
1029 (compile '(let ((f (lambda* (x #:key y #:allow-other-keys)
1030 y)))
1031 (f 2 #:Z 3))
1032 #:opts %opts-w-arity
1033 #:to 'assembly)))))))