RubyToC 1.0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,838 @@
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ $TESTING = true
4
+
5
+ require 'test/unit'
6
+ require 'type_checker'
7
+ require 'r2ctestcase'
8
+
9
+ # Test::Unit::Assertions.use_pp = false
10
+
11
+ class DumbClass # ZenTest SKIP
12
+ def empty
13
+ end
14
+ end
15
+
16
+ class X # ZenTest SKIP
17
+ VALUE = 42
18
+ end
19
+
20
+ class TestTypeChecker < R2CTestCase
21
+
22
+ def setup
23
+ @type_checker = TypeChecker.new
24
+ @processor = @type_checker
25
+ @type_checker.env.add :argl, Type.long
26
+ @type_checker.env.add :args, Type.str
27
+ @type_checker.env.add :arrayl, Type.long_list
28
+ @type_checker.env.add :arrayl2, Type.long_list
29
+ @type_checker.env.add :arrays, Type.str_list
30
+ @type_checker.genv.add :SyntaxError, Type.fucked
31
+ @type_checker.genv.add :Exception, Type.fucked
32
+ end
33
+
34
+ def test_and
35
+ input = t(:and, t(:true), t(:false))
36
+ output = t(:and, t(:true, Type.bool), t(:false, Type.bool), Type.bool)
37
+
38
+ assert_equal output, @type_checker.process(input)
39
+ end
40
+
41
+ def test_bootstrap
42
+ # bootstrap is automatically called by initialize
43
+ # TODO should we check for EVERYTHING we expect?
44
+
45
+ assert_equal Type.file, @type_checker.genv.lookup(:$stdin)
46
+ assert_equal Type.file, @type_checker.genv.lookup(:$stdout)
47
+ assert_equal Type.file, @type_checker.genv.lookup(:$stderr)
48
+
49
+ assert_equal(Type.function(Type.long, [Type.long], Type.bool),
50
+ @type_checker.functions[:>])
51
+ end
52
+
53
+ def test_functions
54
+ # bootstrap populates functions
55
+ assert @type_checker.functions.has_key?(:puts)
56
+ assert_equal(Type.function(Type.long, [Type.long], Type.bool),
57
+ @type_checker.functions[:>])
58
+ end
59
+
60
+ def test_env
61
+ @type_checker.env.add :blah, Type.long
62
+ assert_equal Type.long, @type_checker.env.lookup(:blah)
63
+ end
64
+
65
+ def test_genv
66
+ assert_equal Type.file, @type_checker.genv.lookup(:$stderr)
67
+ end
68
+
69
+ def test_translate
70
+ result = @type_checker.translate DumbClass, :empty
71
+ expect = t(:defn,
72
+ :empty,
73
+ t(:args),
74
+ t(:scope,
75
+ t(:block,
76
+ t(:nil, Type.value), Type.unknown), Type.void),
77
+ Type.function(Type.unknown, [], Type.void))
78
+ assert_equal(expect, result)
79
+ end
80
+
81
+ def test_process_args
82
+ @type_checker.env.extend
83
+
84
+ input = t(:args, :foo, :bar)
85
+ output = t(:args,
86
+ t(:foo, Type.unknown),
87
+ t(:bar, Type.unknown))
88
+
89
+ assert_equal output, @type_checker.process(input)
90
+ end
91
+
92
+ def test_process_args_empty
93
+ input = t(:args)
94
+ output = t(:args)
95
+ # TODO: this should be superseded by the new array functionality
96
+
97
+ assert_equal output, @type_checker.process(input)
98
+ end
99
+
100
+ def test_process_array_single
101
+ add_fake_var :arg1, Type.long
102
+
103
+ input = t(:array, t(:lvar, :arg1))
104
+ output = t(:array, t(:lvar, :arg1, Type.long))
105
+
106
+ result = @type_checker.process(input)
107
+
108
+ assert_equal Type.homo, result.sexp_type
109
+ assert_equal [ Type.long ], result.sexp_types
110
+ assert_equal output, result
111
+ end
112
+
113
+ def test_process_array_multiple
114
+ add_fake_var :arg1, Type.long
115
+ add_fake_var :arg2, Type.str
116
+
117
+ input = t(:array, t(:lvar, :arg1), t(:lvar, :arg2))
118
+ output = t(:array,
119
+ t(:lvar, :arg1, Type.long),
120
+ t(:lvar, :arg2, Type.str))
121
+
122
+ assert_equal output, @type_checker.process(input)
123
+ end
124
+
125
+ def test_process_call_defined
126
+ add_fake_function :name, Type.void, Type.long, Type.str
127
+ input = t(:call,
128
+ nil,
129
+ :name,
130
+ t(:arglist, t(:str, "foo")))
131
+ output = t(:call,
132
+ nil,
133
+ :name,
134
+ t(:arglist, t(:str, "foo", Type.str)),
135
+ Type.long)
136
+
137
+ assert_equal output, @type_checker.process(input)
138
+ end
139
+
140
+ def test_process_call_defined_rhs
141
+ add_fake_function :name3, Type.long, Type.long, Type.str
142
+ input = t(:call,
143
+ t(:lit, 1),
144
+ :name3,
145
+ t(:arglist, t(:str, "foo")))
146
+ output = t(:call,
147
+ t(:lit, 1, Type.long),
148
+ :name3,
149
+ t(:arglist, t(:str, "foo", Type.str)),
150
+ Type.long)
151
+
152
+ assert_equal output, @type_checker.process(input)
153
+ end
154
+
155
+ def test_process_call_undefined
156
+ input = t(:call, nil, :name, nil)
157
+ output = t(:call, nil, :name, nil, Type.unknown)
158
+
159
+ assert_equal output, @type_checker.process(input)
160
+ # FIX returns unknown in s()
161
+ assert_equal(Type.function(Type.unknown, [], Type.unknown),
162
+ @type_checker.functions[:name])
163
+ end
164
+
165
+ def test_process_call_unify_1
166
+ add_fake_var :number, Type.long
167
+ input = t(:call,
168
+ t(:lit, 1),
169
+ :==,
170
+ t(:arglist,
171
+ t(:lvar, :number)))
172
+ output = t(:call,
173
+ t(:lit, 1, Type.long),
174
+ :==,
175
+ t(:arglist,
176
+ t(:lvar, :number, Type.long)),
177
+ Type.bool)
178
+
179
+ assert_equal output, @type_checker.process(input)
180
+ end
181
+
182
+ def test_process_call_unify_2
183
+ add_fake_var :number1, Type.unknown
184
+ add_fake_var :number2, Type.unknown
185
+
186
+ input = t(:call,
187
+ t(:lit, 1),
188
+ :==,
189
+ t(:arglist, t(:lvar, :number1)))
190
+ output = t(:call,
191
+ t(:lit, 1, Type.long),
192
+ :==,
193
+ t(:arglist,
194
+ t(:lvar, :number1, Type.long)),
195
+ Type.bool)
196
+
197
+ assert_equal output, @type_checker.process(input)
198
+
199
+ input = t(:call,
200
+ t(:lvar, :number2),
201
+ :==,
202
+ t(:arglist, t(:lit, 1)))
203
+ output = t(:call,
204
+ t(:lvar, :number2, Type.long),
205
+ :==,
206
+ t(:arglist,
207
+ t(:lit, 1, Type.long)),
208
+ Type.bool)
209
+
210
+ assert_equal output, @type_checker.process(input)
211
+ end
212
+
213
+ def test_process_call_unify_3
214
+ a_type = Type.unknown
215
+ add_fake_var :a, a_type # TODO: Type.unknown
216
+
217
+ # def unify_3_outer(a)
218
+ #
219
+ # unk
220
+ # ^
221
+ # |
222
+ # outer(., ., [+])
223
+
224
+ # assume the environment got everything set up correctly
225
+ add_fake_function(:unify_3_outer, Type.void, Type.void, a_type)
226
+
227
+ assert_equal(a_type,
228
+ @type_checker.functions[:unify_3_outer].list_type.formal_types[0])
229
+
230
+ # unify_3_inner(a) # call
231
+ #
232
+ # outer(., ., [+])
233
+ # |
234
+ # v
235
+ # unk
236
+ # ^
237
+ # |
238
+ # inner(., ., [+])
239
+
240
+ @type_checker.process(t(:call, t(:nil),
241
+ :unify_3_inner,
242
+ t(:arglist, t(:lvar, :a))))
243
+
244
+ assert_equal a_type, @type_checker.env.lookup(:a)
245
+ assert_equal(@type_checker.env.lookup(:a),
246
+ @type_checker.functions[:unify_3_inner].list_type.formal_types[0])
247
+
248
+ # def unify_3_inner(a)
249
+ # a = 1
250
+ # end
251
+ #
252
+ # outer(., ., [+])
253
+ # |
254
+ # v
255
+ # long
256
+ # ^
257
+ # |
258
+ # inner(., ., [+])
259
+
260
+ @type_checker.env.scope do
261
+ @type_checker.env.add :a, a_type
262
+
263
+ @type_checker.process t(:lasgn, :a, t(:lit, 1))
264
+ end
265
+
266
+ assert_equal a_type, Type.long
267
+
268
+ assert_equal(@type_checker.functions[:unify_3_inner].list_type.formal_types[0],
269
+ @type_checker.functions[:unify_3_outer].list_type.formal_types[0])
270
+ end
271
+
272
+ def test_defn_call_unify
273
+
274
+ # pre-registered function, presumibly through another :call elsewhere
275
+ add_fake_function :specific, Type.unknown, Type.unknown, Type.unknown
276
+
277
+ # now in specific, unify with a long
278
+ # puts "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
279
+ # pp @type_checker.functions
280
+ s = @type_checker.process(s(:defn, :specific,
281
+ s(:args, :x),
282
+ s(:scope,
283
+ s(:block,
284
+ s(:lasgn, :x, s(:lit, 2))))))
285
+ # pp @type_checker.functions
286
+ s_type = @type_checker.functions[:specific]
287
+
288
+ # p s_type
289
+
290
+ assert_equal(Type.long,
291
+ s_type.list_type.formal_types[0])
292
+ # HACK flunk "eric hasn't finished writing me yet. guilt. guilt. guilt."
293
+ end
294
+
295
+ def test_process_call_case_equal_long
296
+ add_fake_var :number, Type.unknown
297
+
298
+ input = t(:call,
299
+ t(:lit, 1),
300
+ :===,
301
+ t(:arglist, t(:lvar, :number)))
302
+ output = t(:call,
303
+ t(:lit, 1, Type.long),
304
+ :case_equal_long,
305
+ t(:arglist,
306
+ t(:lvar, :number, Type.long)),
307
+ Type.bool)
308
+
309
+ assert_equal output, @type_checker.process(input)
310
+ end
311
+
312
+ def test_process_call_case_equal_string
313
+ add_fake_var :string, Type.unknown
314
+
315
+ input = t(:call,
316
+ t(:str, 'foo'),
317
+ :===,
318
+ t(:arglist, t(:lvar, :string)))
319
+ output = t(:call,
320
+ t(:str, 'foo', Type.str),
321
+ :case_equal_str,
322
+ t(:arglist,
323
+ t(:lvar, :string, Type.str)),
324
+ Type.bool)
325
+
326
+ assert_equal output, @type_checker.process(input)
327
+ end
328
+
329
+ # HACK: putting class X above w/ some consts
330
+ def test_process_class
331
+ input = s(:class, :X, :Object,
332
+ s(:defn, :meth,
333
+ s(:args, :x),
334
+ s(:scope,
335
+ s(:block,
336
+ s(:lasgn, :x, s(:const, :VALUE))))))
337
+ output = t(:class, :X, :Object,
338
+ t(:defn, :meth,
339
+ t(:args, t(:x, Type.long)),
340
+ t(:scope,
341
+ t(:block,
342
+ t(:lasgn, :x,
343
+ t(:const, :VALUE, Type.long),
344
+ Type.long),
345
+ Type.unknown),
346
+ Type.void),
347
+ Type.function(Type.unknown, [Type.long], Type.void)),
348
+ Type.zclass)
349
+
350
+ assert_equal output, @type_checker.process(input)
351
+ end
352
+
353
+ def test_process_const
354
+ assert_raises NameError do
355
+ @type_checker.process s(:const, :NonExistant)
356
+ end
357
+ end
358
+
359
+ def test_process_cvar
360
+ input = s(:cvar, :name)
361
+ output = t(:cvar, :name, Type.unknown)
362
+
363
+ assert_equal output, @type_checker.process(input)
364
+ end
365
+
366
+ def test_process_cvasgn
367
+ input = s(:cvasgn, :name, s(:lit, 4))
368
+ output = t(:cvasgn, :name, t(:lit, 4, Type.long), Type.unknown)
369
+
370
+ assert_equal output, @type_checker.process(input)
371
+ end
372
+
373
+ def test_process_block
374
+ input = t(:block, t(:return, t(:nil)))
375
+ # FIX: should this really be void for return?
376
+ output = t(:block,
377
+ t(:return,
378
+ t(:nil, Type.value),
379
+ Type.void),
380
+ Type.unknown)
381
+
382
+ assert_equal output, @type_checker.process(input)
383
+ end
384
+
385
+ def test_process_block_multiple
386
+ input = t(:block,
387
+ t(:str, :foo),
388
+ t(:return, t(:nil)))
389
+ output = t(:block,
390
+ t(:str, :foo, Type.str),
391
+ t(:return,
392
+ t(:nil, Type.value),
393
+ Type.void),
394
+ Type.unknown)
395
+
396
+ assert_equal output, @type_checker.process(input)
397
+ end
398
+
399
+ def test_process_dasgn_curr
400
+ @type_checker.env.extend
401
+ input = t(:dasgn_curr, :x)
402
+ output = t(:dasgn_curr, :x, Type.unknown)
403
+
404
+ assert_equal output, @type_checker.process(input)
405
+ # HACK: is this a valid test??? it was in ruby_to_c:
406
+ # assert_equal Type.long, @type_checker.env.lookup(:x)
407
+ end
408
+
409
+ def test_process_defn
410
+ function_type = Type.function s(), Type.void
411
+ input = t(:defn,
412
+ :empty,
413
+ t(:args),
414
+ t(:scope))
415
+ output = t(:defn,
416
+ :empty,
417
+ t(:args),
418
+ t(:scope, Type.void),
419
+ function_type)
420
+
421
+ assert_equal output, @type_checker.process(input)
422
+ end
423
+
424
+ def test_process_dstr
425
+ add_fake_var :var, Type.str
426
+ input = t(:dstr,
427
+ "var is ",
428
+ t(:lvar, :var),
429
+ t(:str, ". So there."))
430
+ output = t(:dstr, "var is ",
431
+ t(:lvar, :var, Type.str),
432
+ t(:str, ". So there.", Type.str),
433
+ Type.str)
434
+
435
+ assert_equal output, @type_checker.process(input)
436
+ end
437
+
438
+ def test_process_dvar
439
+ add_fake_var :dvar, Type.long
440
+ input = t(:dvar, :dvar)
441
+ output = t(:dvar, :dvar, Type.long)
442
+
443
+ assert_equal output, @type_checker.process(input)
444
+ end
445
+
446
+ def test_process_false
447
+ input = t(:false)
448
+ output = t(:false, Type.bool)
449
+
450
+ assert_equal output, @type_checker.process(input)
451
+ end
452
+
453
+ def test_gasgn
454
+ input = s(:gasgn, :$blah, s(:lit, 42))
455
+ expected = t(:gasgn, :$blah, t(:lit, 42, Type.long), Type.long)
456
+
457
+ assert_equal expected, @type_checker.process(input)
458
+ end
459
+
460
+ def test_process_gvar_defined
461
+ add_fake_gvar :$arg, Type.long
462
+ input = t(:gvar, :$arg)
463
+ output = t(:gvar, :$arg, Type.long)
464
+
465
+ assert_equal output, @type_checker.process(input)
466
+ end
467
+
468
+ def test_process_gvar_undefined
469
+ input = t(:gvar, :$arg)
470
+ output = t(:gvar, :$arg, Type.unknown)
471
+
472
+ assert_equal output, @type_checker.process(input)
473
+ end
474
+
475
+ def test_process_iasgn
476
+ input = s(:iasgn, :@blah, s(:lit, 42))
477
+ expected = t(:iasgn, :@blah, t(:lit, 42, Type.long), Type.long)
478
+
479
+ assert_equal expected, @type_checker.process(input)
480
+ end
481
+
482
+ def test_process_if
483
+ input = t(:if,
484
+ t(:call,
485
+ t(:lit, 1),
486
+ :==,
487
+ t(:arglist, t(:lit, 2))),
488
+ t(:str, "not equal"),
489
+ nil)
490
+ output = t(:if,
491
+ t(:call,
492
+ t(:lit, 1, Type.long),
493
+ :==,
494
+ t(:arglist,
495
+ t(:lit, 2, Type.long)),
496
+ Type.bool),
497
+ t(:str, "not equal", Type.str),
498
+ nil,
499
+ Type.str)
500
+
501
+ assert_equal output, @type_checker.process(input)
502
+ end
503
+
504
+ def test_process_if_else
505
+ input = t(:if,
506
+ t(:call,
507
+ t(:lit, 1),
508
+ :==,
509
+ t(:arglist, t(:lit, 2))),
510
+ t(:str, "not equal"),
511
+ t(:str, "equal"))
512
+ output = t(:if,
513
+ t(:call,
514
+ t(:lit, 1, Type.long),
515
+ :==,
516
+ t(:arglist, t(:lit, 2, Type.long)),
517
+ Type.bool),
518
+ t(:str, "not equal", Type.str),
519
+ t(:str, "equal", Type.str),
520
+ Type.str)
521
+
522
+ assert_equal output, @type_checker.process(input)
523
+ end
524
+
525
+ def test_process_iter
526
+ @type_checker.env.extend
527
+ var_type = Type.long_list
528
+ add_fake_var :array, var_type
529
+ input = t(:iter,
530
+ t(:call,
531
+ t(:lvar, :array),
532
+ :each,
533
+ nil),
534
+ t(:dasgn_curr, :x),
535
+ t(:call,
536
+ nil,
537
+ :puts,
538
+ t(:arglist,
539
+ t(:call,
540
+ t(:dvar, :x),
541
+ :to_s,
542
+ nil))))
543
+ output = t(:iter,
544
+ t(:call,
545
+ t(:lvar, :array, var_type),
546
+ :each,
547
+ nil,
548
+ Type.unknown),
549
+ t(:dasgn_curr, :x, Type.long),
550
+ t(:call,
551
+ nil,
552
+ :puts,
553
+ t(:arglist,
554
+ t(:call,
555
+ t(:dvar, :x, Type.long),
556
+ :to_s,
557
+ nil,
558
+ Type.str)),
559
+ Type.void),
560
+ Type.void)
561
+
562
+ assert_equal output, @type_checker.process(input)
563
+ end
564
+
565
+ def test_process_ivar
566
+ @type_checker.env.add :@blah, Type.long
567
+ input = s(:ivar, :@blah)
568
+ expected = t(:ivar, :@blah, Type.long)
569
+
570
+ assert_equal expected, @type_checker.process(input)
571
+ end
572
+
573
+ def test_process_lasgn
574
+ @type_checker.env.extend # FIX: this is a design flaw... examine irb sess:
575
+ # require 'sexp_processor'
576
+ # require 'type_checker'
577
+ # tc = TypeChecker.new
578
+ # s = t(:lasgn, :var, t(:str, "foo"))
579
+ # tc.process(s)
580
+ # => raises
581
+ # tc.env.extend
582
+ # tc.process(s)
583
+ # => raises elsewhere... etc etc etc
584
+ # makes debugging very difficult
585
+ input = t(:lasgn, :var, t(:str, "foo"))
586
+ output = t(:lasgn, :var,
587
+ t(:str, "foo", Type.str),
588
+ Type.str)
589
+
590
+ assert_equal output, @type_checker.process(input)
591
+ end
592
+
593
+ def test_process_lasgn_array
594
+ @type_checker.env.extend
595
+ input = t(:lasgn,
596
+ :var,
597
+ t(:array,
598
+ t(:str, "foo"),
599
+ t(:str, "bar")))
600
+ output = t(:lasgn, :var,
601
+ t(:array,
602
+ t(:str, "foo", Type.str),
603
+ t(:str, "bar", Type.str)),
604
+ Type.str_list)
605
+
606
+ assert_equal output, @type_checker.process(input)
607
+ end
608
+
609
+ def test_process_lit_long
610
+ input = t(:lit, 1)
611
+ output = t(:lit, 1, Type.long)
612
+
613
+ assert_equal output, @type_checker.process(input)
614
+ end
615
+
616
+ def test_process_lit_sym
617
+ input = t(:lit, :sym)
618
+ output = t(:lit, :sym, Type.symbol)
619
+
620
+ assert_equal output, @type_checker.process(input)
621
+ end
622
+
623
+ def test_process_lit_float
624
+ input = t(:lit, 1.0)
625
+ output = t(:lit, 1.0, Type.float)
626
+
627
+ assert_equal output, @type_checker.process(input)
628
+ end
629
+
630
+ def test_process_lvar
631
+ add_fake_var :arg, Type.long
632
+ input = t(:lvar, :arg)
633
+ output = t(:lvar, :arg, Type.long)
634
+
635
+ assert_equal output, @type_checker.process(input)
636
+ end
637
+
638
+ def test_process_nil
639
+ input = t(:nil)
640
+ output = t(:nil, Type.value)
641
+
642
+ assert_equal output, @type_checker.process(input)
643
+ end
644
+
645
+ def test_process_not
646
+ input = t(:not, t(:true))
647
+ output = t(:not, t(:true, Type.bool), Type.bool)
648
+
649
+ assert_equal output, @type_checker.process(input)
650
+ end
651
+
652
+ def test_process_or
653
+ input = t(:or, t(:true), t(:false))
654
+ output = t(:or, t(:true, Type.bool), t(:false, Type.bool), Type.bool)
655
+
656
+ assert_equal output, @type_checker.process(input)
657
+ end
658
+
659
+ def test_process_rescue
660
+ assert_raises RuntimeError do
661
+ @type_checker.process s(:rescue, s(:true), s(:true))
662
+ end
663
+ end
664
+
665
+ def test_process_return
666
+ input = t(:return, t(:nil))
667
+ output = t(:return, t(:nil, Type.value), Type.void)
668
+
669
+ assert_equal output, @type_checker.process(input)
670
+ end
671
+
672
+ # HACK is this test valid? I don't think so
673
+ # def test_process_return_empty
674
+ # input = t(:return)
675
+ # output = t(:return, t(:nil, Type.value), Type.void)
676
+ #
677
+ # assert_equal output, @type_checker.process(input)
678
+ # end
679
+
680
+ def test_process_str
681
+ input = t(:str, "foo")
682
+ output = t(:str, "foo", Type.str)
683
+
684
+ assert_equal output, @type_checker.process(input)
685
+ end
686
+
687
+ def test_process_scope
688
+ input = t(:scope,
689
+ t(:block,
690
+ t(:return, t(:nil))))
691
+ output = t(:scope,
692
+ t(:block,
693
+ t(:return,
694
+ t(:nil, Type.value),
695
+ Type.void),
696
+ Type.unknown), # FIX ? do we care about block?
697
+ Type.void)
698
+
699
+ assert_equal output, @type_checker.process(input)
700
+ end
701
+
702
+ def test_process_scope_empty
703
+ input = t(:scope)
704
+ output = t(:scope, Type.void)
705
+
706
+ assert_equal output, @type_checker.process(input)
707
+ end
708
+
709
+ def test_process_true
710
+ input = t(:true)
711
+ output = t(:true, Type.bool)
712
+
713
+ assert_equal output, @type_checker.process(input)
714
+ end
715
+
716
+ def test_process_unless
717
+ input = t(:if,
718
+ t(:call,
719
+ t(:lit, 1),
720
+ :==,
721
+ t(:arglist, t(:lit, 2))),
722
+ nil,
723
+ t(:str, "equal"))
724
+ output = t(:if,
725
+ t(:call,
726
+ t(:lit, 1, Type.long),
727
+ :==,
728
+ t(:arglist,
729
+ t(:lit, 2, Type.long)),
730
+ Type.bool),
731
+ nil,
732
+ t(:str, "equal", Type.str),
733
+ Type.str)
734
+
735
+ assert_equal output, @type_checker.process(input)
736
+ end
737
+
738
+ def test_process_while
739
+ input = t(:while, t(:true), t(:call, t(:lit, 1), :to_s, nil), true)
740
+ expected = t(:while,
741
+ t(:true, Type.bool),
742
+ t(:call, t(:lit, 1, Type.long), :to_s, nil,
743
+ Type.str), true)
744
+
745
+ assert_equal expected, @type_checker.process(input)
746
+ end
747
+
748
+ def add_fake_function(name, reciever_type, return_type, *arg_types)
749
+ @type_checker.functions.add_function(name,
750
+ Type.function(reciever_type, arg_types, return_type))
751
+ end
752
+
753
+ def add_fake_var(name, type)
754
+ @type_checker.env.extend
755
+ @type_checker.env.add name, type
756
+ end
757
+
758
+ def add_fake_gvar(name, type)
759
+ @type_checker.genv.add name, type
760
+ end
761
+
762
+ # HACK: this needs to be set up w/ determine args in test_type_checker
763
+ # "unknown_args" => {
764
+ # "ParseTree" => [:defn, :unknown_args,
765
+ # [:scope, [:block, [:args, :arg1, :arg2], [:return, [:lvar, :arg1]]]]],
766
+ # "Rewriter" => s(:defn, :unknown_args,
767
+ # s(:args, :arg1, :arg2),
768
+ # s(:scope,
769
+ # s(:block,
770
+ # s(:return, s(:lvar, :arg1))))),
771
+ # "TypeChecker" => t(:defn, :unknown_args,
772
+ # t(:args,
773
+ # t(:arg1, Type.long),
774
+ # t(:arg2, Type.str)),
775
+ # t(:scope,
776
+ # t(:block,
777
+ # t(:return,
778
+ # t(:lvar,
779
+ # :arg1,
780
+ # Type.long),
781
+ # Type.void),
782
+ # Type.unknown),
783
+ # Type.void),
784
+ # Type.function(Type.unknown, [Type.long, Type.str], Type.long)),
785
+ # "R2CRewriter" => :same,
786
+ # "RubyToC" => "long
787
+ # unknown_args(long arg1, str arg2) {
788
+ # return arg1;
789
+ # }",
790
+ # },
791
+
792
+ # "determine_args" => {
793
+ # "ParseTree" => [:defn, :determine_args,
794
+ # [:scope, [:block,
795
+ # [:args],
796
+ # [:call, [:lit, 5], :==,
797
+ # [:array,
798
+ # [:fcall, :unknown_args,
799
+ # [:array, [:lit, 4], [:str, "known"]]]]]]]],
800
+ # "Rewriter" => s(:defn, :determine_args,
801
+ # s(:args),
802
+ # s(:scope,
803
+ # s(:block,
804
+ # s(:call,
805
+ # s(:lit, 5), :==,
806
+ # s(:arglist, s(:call, nil,
807
+ # :unknown_args,
808
+ # s(:arglist,
809
+ # s(:lit, 4),
810
+ # s(:str, "known")))))))),
811
+ # "TypeChecker" => t(:defn, :determine_args,
812
+ # t(:args),
813
+ # t(:scope,
814
+ # t(:block,
815
+ # t(:call,
816
+ # t(:lit,
817
+ # 5,
818
+ # Type.long),
819
+ # :==,
820
+ # t(:arglist,
821
+ # t(:call,
822
+ # nil,
823
+ # :unknown_args,
824
+ # t(:arglist,
825
+ # t(:lit, 4, Type.long),
826
+ # t(:str, "known", Type.str)),
827
+ # Type.long)),
828
+ # Type.bool),
829
+ # Type.unknown),
830
+ # Type.void),
831
+ # Type.function(Type.unknown, [], Type.void)),
832
+ # "R2CRewriter" => :same,
833
+ # "RubyToC" => "void\ndetermine_args() {\n5 == unknown_args(4, \"known\");\n}",
834
+ # },
835
+
836
+
837
+ end
838
+