aboutsummaryrefslogtreecommitdiffstats
path: root/csc/cps-test.csc
blob: 6439d785f62265e3034bc04e4c37209f5f06a05f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
(define-library (csc cps-test)
  (import (scheme base)
          (only (csc gensym)
            gensym
            gensym?)
          (only (csc ir1)
            %constant
            %lexical-ref
            %library-ref
            constant?
            lexical-ref?
            library-ref?
            make-call
            make-call-builtin
            make-constant
            make-define-syntax
            make-if
            make-lambda
            make-letrec
            make-lexical-ref
            make-lexical-set
            make-library-ref
            make-sequence)
          (only (csc ir2)
            %apply
            %branch
            %closure
            %fix
            %globals
            %label
            %primitive
            %variable
            *globals*
            apply?
            branch?
            closure?
            fix?
            globals?
            label?
            make-apply
            make-branch
            make-call-closure
            make-closure
            make-fix
            make-label
            make-primitive
            make-variable
            primitive?
            variable?)
          (only (csc testing)
            assert-equal
            test)
          (csc cps))
  (begin


    (define transform-ir2
      (list
        (cons constant? %constant)
        (cons lexical-ref? %lexical-ref)
        (cons library-ref? %library-ref)
        (cons variable? %variable)
        (cons globals? %globals)
        (cons label? %label)
        (cons primitive? %primitive)
        (cons branch? %branch)
        (cons apply? %apply)
        (cons closure? %closure)
        (cons fix? %fix)
        (cons gensym? (lambda (x) 'gensym))))


    (define (test-ref name)
      (make-lexical-ref name (gensym)))


    (define (tail x)
      (make-apply (test-ref 'tail) (list x)))


    (test atom-const
      (assert-equal
        (make-apply (test-ref 'tail) (list (make-constant 5)))
        (ir1->ir2 (make-constant 5) tail)
        transform-ir2))


    (test atom-lexical-ref
      (assert-equal
        (make-apply (test-ref 'tail) (list (test-ref 'var)))
        (ir1->ir2 (test-ref 'var) tail)
        transform-ir2))


    (test atom-library-ref
      (assert-equal
        (make-primitive 'peek (list *globals* (make-library-ref 'var '(csc builtins))) (list (test-ref 'generated-symbol))
          (make-apply (test-ref 'tail) (list (test-ref 'generated-symbol))))
        (ir1->ir2 (make-library-ref 'var '(csc builtins)) tail)
        transform-ir2))


    (test lexical-set
      (assert-equal
        (make-primitive 'poke (list (make-constant 5) (test-ref 'var) (make-constant 0)) '()
          (make-apply (test-ref 'tail) (list (make-constant #f))))
        (ir1->ir2 (make-lexical-set (test-ref 'var) (make-constant 5))
                  tail)
        transform-ir2))


    (test no-op-define-syntax
      (assert-equal
        (make-apply (test-ref 'tail) (list (make-constant #f)))
        (ir1->ir2 (make-define-syntax 'name '(transformer))
                  tail)
        transform-ir2))


    (test branch
      (assert-equal
        (make-fix
          (list
            (make-closure (test-ref 'generated-symbol) (list (test-ref 'generated-symbol))
              (make-apply (test-ref 'tail) (list (test-ref 'generated-symbol)))))
          (make-branch (make-constant #t)
            (make-apply (test-ref 'generated-symbol) (list (make-constant 1)))
            (make-apply (test-ref 'generated-symbol) (list (make-constant 2)))))
        (ir1->ir2 (make-if (make-constant #t)
                    (make-constant 1)
                    (make-constant 2))
                  tail)
        transform-ir2))


    (test call-closure
      (assert-equal
        (make-fix
          (list
            (make-closure (test-ref 'generated-symbol) (list (test-ref 'generated-symbol))
              (make-apply (test-ref 'tail) (list (test-ref 'generated-symbol)))))
          (make-fix
            (list (make-closure (test-ref 'generated-symbol) (list (test-ref 'generated-symbol) (test-ref 'generated-symbol))
                    (make-primitive 'poke (list (make-constant 0) (test-ref 'generated-symbol) (make-constant 0)) '()
                      (make-primitive 'poke (list (make-constant 2) (test-ref 'generated-symbol) (make-constant 1)) '()
                        (make-primitive 'poke (list (make-constant 10) (test-ref 'generated-symbol) (make-constant 2)) '()
                          (make-primitive 'poke (list (make-constant 20) (test-ref 'generated-symbol) (make-constant 3)) '()
                            (make-fix
                              (list (make-closure (test-ref 'generated-symbol) (list (test-ref 'generated-symbol))
                                      (make-apply (test-ref 'generated-symbol) (list (test-ref 'generated-symbol)))))
                              (make-apply (test-ref 'f) (list (test-ref 'generated-symbol) (test-ref 'generated-symbol))))))))))
            (make-primitive 'alloc (list (make-constant 4)) (list (test-ref 'generated-symbol))
              (make-apply (test-ref 'generated-symbol) (list (test-ref 'generated-symbol) (test-ref 'generated-symbol))))))
        (ir1->ir2 (make-call (test-ref 'f) (list (make-constant 10) (make-constant 20)))
                  tail)
        transform-ir2))


    (test call-builtin-alloc
      (assert-equal
        (make-primitive 'alloc (list (make-constant 10)) (list (test-ref 'generated-symbol))
          (make-apply (test-ref 'tail) (list (test-ref 'generated-symbol))))
        (ir1->ir2 (make-call-builtin 'alloc (list (make-constant 10))) tail)
        transform-ir2))


    (test call-builtin-peek
      (assert-equal
        (make-primitive 'alloc (list (make-constant 1)) (list (test-ref 'generated-symbol))
          (make-primitive 'peek (list (test-ref 'generated-symbol) (make-constant 0)) (list (test-ref 'generated-symbol))
            (make-apply (test-ref 'tail) (list (test-ref 'generated-symbol)))))
        (ir1->ir2
          (make-call-builtin 'peek (list (make-call-builtin 'alloc (list (make-constant 1))) (make-constant 0)))
          tail)
        transform-ir2))


    (test call-builtin-poke
      (assert-equal
        (make-primitive 'alloc (list (make-constant 1)) (list (test-ref 'generated-symbol))
          (make-primitive 'poke (list (make-constant 10) (test-ref 'generated-symbol) (make-constant 0)) '()
            (make-apply (test-ref 'tail) (list (make-constant #f)))))
        (ir1->ir2
          (make-call-builtin 'poke (list (make-constant 10)
                                         (make-call-builtin 'alloc (list (make-constant 1)))
                                         (make-constant 0)))
          tail)
        transform-ir2))


    (test sequence
      (assert-equal
        (make-primitive 'poke (list (make-constant 5) (test-ref 'a) (make-constant 0)) '()
          (make-primitive 'poke (list (make-constant 6) (test-ref 'b) (make-constant 0)) '()
            (make-apply (test-ref 'tail) (list (make-constant #f)))))
        (ir1->ir2 (make-sequence (make-lexical-set (test-ref 'a) (make-constant 5))
                                 (make-lexical-set (test-ref 'b) (make-constant 6)))
                  tail)
        transform-ir2))


    ; It's pretty bad
    (test closure-rest
      (assert-equal
        (make-fix
          (list (make-closure (test-ref 'generated-symbol)
                                      (list (test-ref 'generated-symbol) (test-ref 'generated-symbol))
                  (make-primitive 'peek (list (test-ref 'generated-symbol) (make-constant 1)) (list (test-ref 'generated-symbol))
                    (make-primitive 'int<? (list (test-ref 'generated-symbol) (make-constant 0)) (list (test-ref 'generated-symbol))
                      (make-fix (list (make-closure (test-ref 'generated-symbol)
                                                    (list (test-ref 'generated-symbol))
                                        (make-apply (test-ref 'generated-symbol) (list (test-ref 'generated-symbol)))))
                        (make-branch (test-ref 'generated-symbol)
                          (make-fix (list (make-closure (test-ref 'generated-symbol)
                                                        (list (test-ref 'generated-symbol))
                                            (make-apply (test-ref 'generated-symbol) (list (test-ref 'generated-symbol)))))
                            (make-primitive 'peek (list *globals* (make-library-ref 'wrong-number-of-arguments '(csc based))) (list (test-ref 'generated-symbol))
                              (make-apply (test-ref 'generated-symbol)
                                          (list (test-ref 'generated-symbol) (test-ref 'generated-symbol)))))
                          (make-fix (list (make-closure (test-ref 'generated-symbol)
                                                        (list (test-ref 'generated-symbol))
                                            (make-apply (test-ref 'generated-symbol) (list (test-ref 'generated-symbol)))))
                            (make-fix
                              (list (make-closure (test-ref 'generated-symbol) (list (test-ref 'generated-symbol) (test-ref 'c))
                                      (make-apply (test-ref 'generated-symbol) (list (make-constant 5)))))
                              (make-fix
                                (list (make-closure (test-ref 'generated-symbol) (list (test-ref 'generated-symbol))
                                        (make-apply (test-ref 'generated-symbol) (list (test-ref 'generated-symbol) (test-ref 'generated-symbol)))))
                                (make-fix
                                  (list (make-closure (test-ref 'generated-symbol) (list (test-ref 'generated-symbol) (test-ref 'generated-symbol))
                                          (make-primitive 'poke (list (make-constant 0) (test-ref 'generated-symbol) (make-constant 0)) '()
                                            (make-primitive 'poke (list (make-constant 2) (test-ref 'generated-symbol) (make-constant 1)) '()
                                              (make-primitive 'poke (list (test-ref 'generated-symbol) (test-ref 'generated-symbol) (make-constant 2)) '()
                                                (make-primitive 'poke (list (make-constant 0) (test-ref 'generated-symbol) (make-constant 3)) '()
                                                  (make-fix
                                                    (list (make-closure (test-ref 'generated-symbol) (list (test-ref 'generated-symbol))
                                                            (make-apply (test-ref 'generated-symbol) (list (test-ref 'generated-symbol)))))
                                                    (make-primitive 'peek (list *globals* (make-library-ref 'vector->list '(csc based))) (list (test-ref 'generated-symbol))
                                                      (make-apply (test-ref 'generated-symbol) (list (test-ref 'generated-symbol) (test-ref 'generated-symbol)))))))))))
                                  (make-primitive 'alloc (list (make-constant 4)) (list (test-ref 'generated-symbol))
                                    (make-apply (test-ref 'generated-symbol) (list (test-ref 'generated-symbol) (test-ref 'generated-symbol))))))))))))))
          (make-apply (test-ref 'tail) (list (test-ref 'generated-symbol))))
        (ir1->ir2 (make-lambda
                    '()
                    (test-ref 'c)
                    (make-constant 5))
                  tail)
        transform-ir2))


    (test letrec-functions
      (define x (test-ref 'x))
      (define f (gensym))
      (assert-equal
        (make-fix
          (list
            (make-closure (test-ref 'f) (list (test-ref 'generated-symbol) (test-ref 'generated-symbol))
              (make-primitive 'peek (list (test-ref 'generated-symbol) (make-constant 1)) (list (test-ref 'generated-symbol))
                (make-primitive 'int=? (list (test-ref 'generated-symbol) (make-constant 1)) (list (test-ref 'generated-symbol))
                  (make-fix
                    (list (make-closure (test-ref 'generated-symbol) (list (test-ref 'generated-symbol))
                            (make-apply (test-ref 'generated-symbol) (list (test-ref 'generated-symbol)))))
                    (make-branch (test-ref 'generated-symbol)
                      (make-fix
                        (list (make-closure (test-ref 'generated-symbol) (list (test-ref 'generated-symbol))
                                (make-apply (test-ref 'generated-symbol) (list (test-ref 'generated-symbol)))))
                        (make-fix
                          (list (make-closure (test-ref 'generated-symbol) (list (test-ref 'generated-symbol) (test-ref 'x))
                                  (make-apply (test-ref 'generated-symbol) (list (test-ref 'x)))))
                          (make-primitive 'peek (list (test-ref 'generated-symbol) (make-constant 2)) (list (test-ref 'generated-symbol))
                            (make-apply (test-ref 'generated-symbol) (list (test-ref 'generated-symbol) (test-ref 'generated-symbol))))))
                      (make-fix
                        (list (make-closure (test-ref 'generated-symbol) (list (test-ref 'generated-symbol))
                                (make-apply (test-ref 'generated-symbol) (list (test-ref 'generated-symbol)))))
                        (make-primitive 'peek (list *globals* (make-library-ref 'wrong-number-of-arguments '(csc based))) (list (test-ref 'generated-symbol))
                          (make-apply (test-ref 'generated-symbol) (list (test-ref 'generated-symbol) (test-ref 'generated-symbol)))))))))))
          (make-fix
            (list
              (make-closure (test-ref 'generated-symbol) (list (test-ref 'generated-symbol))
                (make-apply (test-ref 'tail) (list (test-ref 'generated-symbol)))))
            (make-fix
              (list (make-closure (test-ref 'generated-symbol) (list (test-ref 'generated-symbol) (test-ref 'generated-symbol))
                      (make-primitive 'poke (list (make-constant 0) (test-ref 'generated-symbol) (make-constant 0)) '()
                        (make-primitive 'poke (list (make-constant 1) (test-ref 'generated-symbol) (make-constant 1)) '()
                          (make-primitive 'poke (list (make-constant 10) (test-ref 'generated-symbol) (make-constant 2)) '()
                            (make-fix
                              (list (make-closure (test-ref 'generated-symbol) (list (test-ref 'generated-symbol))
                                      (make-apply (test-ref 'generated-symbol) (list (test-ref 'generated-symbol)))))
                              (make-apply (test-ref 'f) (list (test-ref 'generated-symbol) (test-ref 'generated-symbol)))))))))
              (make-primitive 'alloc (list (make-constant 3)) (list (test-ref 'generated-symbol))
                (make-apply (test-ref 'generated-symbol) (list (test-ref 'generated-symbol) (test-ref 'generated-symbol)))))))
        (ir1->ir2
          (make-letrec #f '(f) (list f)
                       (list (make-lambda (list x) #f x))
            (make-call (make-lexical-ref 'f f) (list (make-constant 10))))
          tail)
        transform-ir2))


    (test letrec-in-order
      (define a (gensym))
      (define b (gensym))
      (assert-equal
        (make-primitive 'alloc (list (make-constant 1)) (list (test-ref 'b))
          (make-primitive 'alloc (list (make-constant 1)) (list (test-ref 'a))
            (make-primitive 'poke (list (make-constant 1) (test-ref 'a) (make-constant 0)) '()
              (make-primitive 'poke (list (test-ref 'a) (test-ref 'b) (make-constant 0)) '()
                (make-apply (test-ref 'tail) (list (test-ref 'b)))))))
        (ir1->ir2
          (make-letrec #t
            '(a b)
            (list a (gensym))
            (list (make-constant 1)
                  (make-lexical-ref 'a a))
            (make-lexical-ref 'b b))
          tail)
        transform-ir2))


    (test letrec-in-order-function
      (assert-equal
        (make-fix
          (list (make-closure (test-ref 'f) (list (test-ref 'generated-symbol) (test-ref 'generated-symbol))
                  (make-primitive 'peek (list (test-ref 'generated-symbol) (make-constant 1)) (list (test-ref 'generated-symbol))
                    (make-primitive 'int=? (list (test-ref 'generated-symbol) (make-constant 0)) (list (test-ref 'generated-symbol))
                      (make-fix
                        (list (make-closure (test-ref 'generated-symbol) (list (test-ref 'generated-symbol))
                                (make-apply (test-ref 'generated-symbol) (list (test-ref 'generated-symbol)))))
                        (make-branch (test-ref 'generated-symbol)
                          (make-apply (test-ref 'generated-symbol) (list (make-constant 5)))
                          (make-fix
                            (list (make-closure (test-ref 'generated-symbol) (list (test-ref 'generated-symbol))
                                    (make-apply (test-ref 'generated-symbol) (list (test-ref 'generated-symbol)))))
                            (make-primitive 'peek (list *globals* (make-library-ref 'wrong-number-of-arguments '(csc based))) (list (test-ref 'generated-symbol))
                              (make-apply (test-ref 'generated-symbol) (list (test-ref 'generated-symbol) (test-ref 'generated-symbol)))))))))))
          (make-apply (test-ref 'tail) (list (make-constant 10))))
        (ir1->ir2
          (make-letrec #t
            '(f)
            (list (gensym))
            (list (make-lambda '() #f (make-constant 5)))
            (make-constant 10))
          tail)
        transform-ir2))


    ; What does the following letrec return?
    ; (letrec* ((f (lambda () x))
    ;           (x (f)))
    ;   x)
    (test letrec-very-cool
      (define f (gensym))
      (define x (gensym))
      (assert-equal
        (make-primitive 'alloc (list (make-constant 1)) (list (test-ref 'x))
          (make-fix
            (list
              (make-closure (test-ref 'f) (list (test-ref 'generated-symbol) (test-ref 'generated-symbol))
                (make-primitive 'peek (list (test-ref 'generated-symbol) (make-constant 1)) (list (test-ref 'generated-symbol))
                  (make-primitive 'int=? (list (test-ref 'generated-symbol) (make-constant 0)) (list (test-ref 'generated-symbol))
                    (make-fix
                      (list (make-closure (test-ref 'generated-symbol) (list (test-ref 'generated-symbol))
                              (make-apply (test-ref 'generated-symbol) (list (test-ref 'generated-symbol)))))
                      (make-branch (test-ref 'generated-symbol)
                        (make-primitive 'peek (list (test-ref 'x) (make-constant 0)) (list (test-ref 'generated-symbol))
                          (make-apply (test-ref 'generated-symbol) (list (test-ref 'generated-symbol))))
                        (make-fix
                          (list (make-closure (test-ref 'generated-symbol) (list (test-ref 'generated-symbol))
                                  (make-apply (test-ref 'generated-symbol) (list (test-ref 'generated-symbol)))))
                          (make-primitive 'peek (list *globals* (make-library-ref 'wrong-number-of-arguments '(csc based))) (list (test-ref 'generated-symbol))
                            (make-apply (test-ref 'generated-symbol) (list (test-ref 'generated-symbol) (test-ref 'generated-symbol)))))))))))
            (make-fix
              (list
                (make-closure (test-ref 'generated-symbol) (list (test-ref 'generated-symbol))
                  (make-primitive 'poke (list (test-ref 'generated-symbol) (test-ref 'x) (make-constant 0)) '()
                    (make-primitive 'peek (list (test-ref 'x) (make-constant 0)) (list (test-ref 'generated-symbol))
                      (make-apply (test-ref 'tail) (list (test-ref 'generated-symbol)))))))
              (make-fix
                (list (make-closure (test-ref 'generated-symbol) (list (test-ref 'generated-symbol) (test-ref 'generated-symbol))
                        (make-primitive 'poke (list (make-constant 0) (test-ref 'generated-symbol) (make-constant 0)) '()
                          (make-primitive 'poke (list (make-constant 0) (test-ref 'generated-symbol) (make-constant 1)) '()
                            (make-fix
                              (list (make-closure (test-ref 'generated-symbol) (list (test-ref 'generated-symbol))
                                      (make-apply (test-ref 'generated-symbol) (list (test-ref 'generated-symbol)))))
                              (make-apply (test-ref 'f) (list (test-ref 'generated-symbol) (test-ref 'generated-symbol))))))))
                (make-primitive 'alloc (list (make-constant 2)) (list (test-ref 'generated-symbol))
                  (make-apply (test-ref 'generated-symbol) (list (test-ref 'generated-symbol) (test-ref 'generated-symbol))))))))
        (ir1->ir2
          (make-letrec #t
            '(f x)
            (list f x)
            (list (make-lambda '() #f (make-lexical-ref 'x x))
                  (make-call (make-lexical-ref 'f f) '()))
            (make-lexical-ref 'x x))
          tail)
        transform-ir2))


    (test set-argument
      (define test-sym (gensym))
      (assert-equal
        (make-fix
          (list
            (make-closure (test-ref 'f) (list (test-ref 'generated-symbol)
                                              (test-ref 'generated-symbol))
              (make-primitive 'peek (list (test-ref 'generated-symbol) (make-constant 1)) (list (test-ref 'generated-symbol))
                (make-primitive 'int=? (list (test-ref 'generated-symbol) (make-constant 1)) (list (test-ref 'generated-symbol))
                  (make-fix
                    (list (make-closure (test-ref 'generated-symbol) (list (test-ref 'generated-symbol))
                            (make-apply (test-ref 'generated-symbol) (list (test-ref 'generated-symbol)))))
                    (make-branch (test-ref 'generated-symbol)
                      (make-fix
                        (list (make-closure (test-ref 'generated-symbol) (list (test-ref 'generated-symbol))
                                (make-apply (test-ref 'generated-symbol) (list (test-ref 'generated-symbol)))))
                        (make-fix
                          (list (make-closure (test-ref 'generated-symbol) (list (test-ref 'generated-symbol) (test-ref 'generated-symbol))
                                  (make-primitive 'alloc (list (make-constant 1)) (list (test-ref 'x))
                                    (make-primitive 'poke (list (test-ref 'generated-symbol) (test-ref 'x) (make-constant 0)) '()
                                      (make-primitive 'poke (list (make-constant 10) (test-ref 'x) (make-constant 0)) '()
                                        (make-apply (test-ref 'generated-symbol) (list (make-constant #f))))))))
                          (make-primitive 'peek (list (test-ref 'generated-symbol) (make-constant 2)) (list (test-ref 'generated-symbol))
                            (make-apply (test-ref 'generated-symbol) (list (test-ref 'generated-symbol) (test-ref 'generated-symbol))))))
                      (make-fix
                        (list (make-closure (test-ref 'generated-symbol) (list (test-ref 'generated-symbol))
                                (make-apply (test-ref 'generated-symbol) (list (test-ref 'generated-symbol)))))
                        (make-primitive 'peek (list *globals* (make-library-ref 'wrong-number-of-arguments '(csc based))) (list (test-ref 'generated-symbol))
                          (make-apply (test-ref 'generated-symbol) (list (test-ref 'generated-symbol) (test-ref 'generated-symbol)))))))))))
          (make-apply (test-ref 'tail) (list (make-constant 5))))
        (ir1->ir2 (make-letrec
                    #f
                    '(f)
                    (list (gensym))
                    (list (make-lambda (list (make-lexical-ref 'x test-sym)) #f
                            (make-lexical-set (make-lexical-ref 'x test-sym) (make-constant 10))))
                    (make-constant 5))
                  tail)
        transform-ir2))

    (test set-function
      (define test-sym (gensym))
      (assert-equal
        (make-primitive 'alloc (list (make-constant 1)) (list (test-ref 'f))
          (make-fix
            (list (make-closure (test-ref 'generated-symbol) (list (test-ref 'generated-symbol) (test-ref 'generated-symbol))
                    (make-primitive 'peek (list (test-ref 'generated-symbol) (make-constant 1)) (list (test-ref 'generated-symbol))
                      (make-primitive 'int=? (list (test-ref 'generated-symbol) (make-constant 0)) (list (test-ref 'generated-symbol))
                        (make-fix
                          (list (make-closure (test-ref 'generated-symbol) (list (test-ref 'generated-symbol))
                                  (make-apply (test-ref 'generated-symbol) (list (test-ref 'generated-symbol)))))
                          (make-branch (test-ref 'generated-symbol)
                            (make-apply (test-ref 'generated-symbol) (list (make-constant 10)))
                            (make-fix
                              (list (make-closure (test-ref 'generated-symbol) (list (test-ref 'generated-symbol))
                                      (make-apply (test-ref 'generated-symbol) (list (test-ref 'generated-symbol)))))
                              (make-primitive 'peek (list *globals* (make-library-ref 'wrong-number-of-arguments '(csc based))) (list (test-ref 'generated-symbol))
                                (make-apply (test-ref 'generated-symbol) (list (test-ref 'generated-symbol) (test-ref 'generated-symbol)))))))))))
            (make-primitive 'poke (list (test-ref 'generated-symbol) (test-ref 'f) (make-constant 0)) '()
              (make-primitive 'poke (list (make-constant 5) (test-ref 'f) (make-constant 0)) '()
                (make-apply (test-ref 'tail) (list (make-constant #f)))))))
        (ir1->ir2 (make-letrec
                    #f
                    '(f)
                    (list test-sym)
                    (list (make-lambda '() #f (make-constant 10)))
                    (make-lexical-set (make-lexical-ref 'f test-sym) (make-constant 5)))
                  tail)
        transform-ir2))


    (define (test-var)
      (make-variable (gensym)))


    (test closure-convert-primitive
      (define a-sym (gensym))
      (define f-sym (gensym))
      (define ret-sym (gensym))
      (define x-sym (gensym))
      (assert-equal
        (make-primitive 'alloc (list (make-constant 1)) (list (test-var))
          (make-fix
            (list
              (make-closure (make-label (gensym)) (list (test-var) (test-var) (test-var))
                (make-primitive 'peek (list (test-var) (make-constant 0)) (list (test-var))
                  (make-primitive 'poke (list (test-var) (test-var) (make-constant 0)) '()
                    (make-primitive 'peek (list (test-var) (make-constant 0)) (list (test-var))
                      (make-apply (test-var) (list (test-var) (make-constant #f))))))))
            (make-primitive 'alloc (list (make-constant 2)) (list (test-var))
              (make-primitive 'poke (list (make-label (gensym)) (test-var) (make-constant 0)) '()
                (make-primitive 'poke (list (test-var) (test-var) (make-constant 1)) '()
                  (make-primitive 'peek (list (test-var) (make-constant 0)) (list (test-var))
                    (make-apply (test-var) (list (test-var) (make-library-ref 'tail '(csc builtins)) (make-constant 10)))))))))
        (closure-convert (make-primitive 'alloc (list (make-constant 1)) (list (make-lexical-ref 'a a-sym))
                           (make-fix
                             (list
                               (make-closure (make-lexical-ref 'f f-sym) (list (make-lexical-ref 'ret ret-sym) (make-lexical-ref 'x x-sym))
                                 (make-primitive 'poke (list (make-lexical-ref 'x x-sym) (make-lexical-ref 'a a-sym) (make-constant 0)) '()
                                   (make-apply (make-lexical-ref 'ret ret-sym) (list (make-constant #f))))))
                             (make-apply (make-lexical-ref 'f f-sym) (list (make-library-ref 'tail '(csc builtins)) (make-constant 10))))))
        transform-ir2))))