ZenHacks 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,23 @@
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ ENV['GEM_SKIP'] = 'ParseTree:RubyInline'
4
+ $:.push 'lib', '../../ParseTree/dev/lib', '../../RubyInline/dev', '../../ruby_to_c/dev'
5
+
6
+ require 'r2c_hacks'
7
+
8
+ class Example
9
+ def example(arg1)
10
+ return "Blah: " + arg1.to_s
11
+ end
12
+ end
13
+
14
+ e = Example.new
15
+ puts "Code (via cat):"
16
+ puts `cat #{$0}`
17
+ puts "sexp:"
18
+ p e.method(:example).to_sexp
19
+ puts "C:"
20
+ puts e.method(:example).to_c
21
+ puts "Ruby:"
22
+ puts e.method(:example).to_ruby
23
+
@@ -0,0 +1,43 @@
1
+ #!/usr/local/bin/ruby -w
2
+ # Code Generated by ZenTest v. 2.2.0
3
+ # classname: asrt / meth = ratio%
4
+ # OrderedHash: 1 / 6 = 16.67%
5
+ # Number of errors detected: 0
6
+
7
+ #require 'test/unit' unless defined? $ZENTEST and $ZENTEST
8
+ require 'test/unit/testcase'
9
+ require 'OrderedHash'
10
+
11
+ class TestOrderedHash < Test::Unit::TestCase
12
+
13
+ def setup
14
+ @k = %w(z y x)
15
+ @h = OrderedHash.new
16
+
17
+ @k.each_with_index do |key, val|
18
+ @h[key] = val + 1
19
+ end
20
+ end
21
+
22
+ def test_keys
23
+ assert_equal @k, @h.keys
24
+ end
25
+
26
+ def test_each
27
+ assert_equal 1, 2
28
+ end
29
+
30
+ def test_each_key
31
+ raise NotImplementedError, 'Need to write test_each_key'
32
+ end
33
+
34
+ def test_each_value
35
+ raise NotImplementedError, 'Need to write test_each_value'
36
+ end
37
+
38
+ def test_index_equals
39
+ raise NotImplementedError, 'Need to write test_index_equals'
40
+ end
41
+ end
42
+
43
+ # Number of errors detected: 1
@@ -0,0 +1,1076 @@
1
+ require 'test/unit/testcase'
2
+
3
+ require 'sexp_processor'
4
+ require 'typed_sexp_processor'
5
+ require 'support'
6
+
7
+ class R2CTestCase < Test::Unit::TestCase
8
+
9
+ attr_accessor :processor # to be defined by subclass
10
+
11
+ def setup
12
+ super
13
+ @processor = nil
14
+ end
15
+
16
+ @@testcase_order = [
17
+ "ParseTree",
18
+ "Rewriter",
19
+ "TypeChecker",
20
+ "R2CRewriter",
21
+ "Ruby2RubyC",
22
+ ]
23
+
24
+ @@testcases = {
25
+
26
+ "accessor" => {
27
+ "ParseTree" => [:defn, :accessor, [:ivar, :@accessor]],
28
+ "Rewriter" => s(:defn, :accessor, s(:args),
29
+ s(:scope,
30
+ s(:block, s(:return, s(:ivar, :@accessor))))),
31
+ "TypeChecker" => :skip,
32
+ "R2CRewriter" => :skip,
33
+ "Ruby2RubyC" => :skip,
34
+ },
35
+
36
+ "accessor_equals" => {
37
+ "ParseTree" => [:defn, :accessor=, [:attrset, :@accessor]],
38
+ "Rewriter" => s(:defn,
39
+ :accessor=,
40
+ s(:args, :arg),
41
+ s(:scope,
42
+ s(:block,
43
+ s(:return,
44
+ s(:iasgn, :@accessor, s(:lvar, :arg)))))),
45
+ "TypeChecker" => :skip,
46
+ "R2CRewriter" => :skip,
47
+ "Ruby2RubyC" => :skip,
48
+ },
49
+
50
+ "defn_bbegin" => {
51
+ "ParseTree" => [:defn, :bbegin,
52
+ [:scope,
53
+ [:block,
54
+ [:args],
55
+ [:begin,
56
+ [:ensure,
57
+ [:rescue,
58
+ [:call, [:lit, 1], :+, [:array, [:lit, 1]]],
59
+ [:resbody,
60
+ [:array, [:const, :SyntaxError]],
61
+ [:block, [:lasgn, :e1, [:gvar, :$!]], [:lit, 2]],
62
+ [:resbody,
63
+ [:array, [:const, :Exception]],
64
+ [:block, [:lasgn, :e2, [:gvar, :$!]], [:lit, 3]]]],
65
+ [:lit, 4]],
66
+ [:lit, 5]]]]]],
67
+ "Rewriter" => s(:defn, :bbegin,
68
+ s(:args),
69
+ s(:scope,
70
+ s(:block,
71
+ s(:begin,
72
+ s(:ensure,
73
+ s(:rescue,
74
+ s(:call, s(:lit, 1), :+, s(:arglist, s(:lit, 1))),
75
+ s(:resbody,
76
+ s(:array, s(:const, :SyntaxError)),
77
+ s(:block, s(:lasgn, :e1, s(:gvar, :$!)),
78
+ s(:lit, 2)),
79
+ s(:resbody,
80
+ s(:array, s(:const, :Exception)),
81
+ s(:block, s(:lasgn, :e2, s(:gvar, :$!)),
82
+ s(:lit, 3)))),
83
+ s(:lit, 4)),
84
+ s(:lit, 5)))))),
85
+ "TypeChecker" => t(:defn, :bbegin,
86
+ t(:args),
87
+ t(:scope,
88
+ t(:block,
89
+ t(:begin,
90
+ t(:ensure,
91
+ t(:rescue,
92
+ t(:call,
93
+ t(:lit, 1, Type.long),
94
+ :+,
95
+ t(:arglist, t(:lit, 1, Type.long)), Type.long),
96
+ t(:resbody,
97
+ t(:array, t(:const, :SyntaxError, Type.fucked)),
98
+ t(:block,
99
+ t(:lasgn, :e1, t(:gvar, :$!, Type.unknown),
100
+ Type.unknown),
101
+ t(:lit, 2, Type.long), Type.unknown),
102
+ t(:resbody,
103
+ t(:array, t(:const, :Exception, Type.fucked)),
104
+ t(:block,
105
+ t(:lasgn, :e2, t(:gvar, :$!, Type.unknown),
106
+ Type.unknown),
107
+ t(:lit, 3, Type.long), Type.unknown),
108
+ Type.unknown), Type.long),
109
+ t(:lit, 4, Type.long), Type.long),
110
+ t(:lit, 5, Type.long))), Type.unknown),
111
+ Type.void),
112
+ Type.function(Type.unknown, [], Type.void)),
113
+ "R2CRewriter" => :same,
114
+ "Ruby2RubyC" => :unsupported,
115
+ },
116
+
117
+ "defn_bmethod_added" => {
118
+ "ParseTree" => [:defn, :bmethod_added,
119
+ [:bmethod,
120
+ [:dasgn_curr, :x],
121
+ [:call, [:dvar, :x], :+, [:array, [:lit, 1]]]]],
122
+ "Rewriter" => s(:defn,
123
+ :bmethod_added,
124
+ s(:args, :x),
125
+ s(:scope,
126
+ s(:block,
127
+ s(:call, s(:lvar, :x), :+, s(:arglist, s(:lit, 1)))))),
128
+ "TypeChecker" => :skip,
129
+ "R2CRewriter" => :skip,
130
+ "Ruby2RubyC" => :skip,
131
+ },
132
+
133
+ "bools" => {
134
+ "ParseTree" => [:defn, :bools,
135
+ [:scope,
136
+ [:block,
137
+ [:args, :arg1],
138
+ [:if,
139
+ [:call, [:lvar, :arg1], "nil?".intern], # emacs is freakin'
140
+ [:return, [:false]],
141
+ [:return, [:true]]]]]],
142
+ "Rewriter" => s(:defn, :bools,
143
+ s(:args, :arg1),
144
+ s(:scope,
145
+ s(:block,
146
+ s(:if,
147
+ s(:call,
148
+ s(:lvar, :arg1),
149
+ :nil?,
150
+ nil),
151
+ s(:return, s(:false)),
152
+ s(:return, s(:true)))))),
153
+ # TODO: why does return false have type void?
154
+ "TypeChecker" => t(:defn, :bools,
155
+ t(:args, t(:arg1, Type.value)),
156
+ t(:scope,
157
+ t(:block,
158
+ t(:if,
159
+ t(:call,
160
+ t(:lvar, :arg1, Type.value),
161
+ :nil?,
162
+ nil,
163
+ Type.bool),
164
+ t(:return,
165
+ t(:false, Type.bool),
166
+ Type.void),
167
+ t(:return,
168
+ t(:true, Type.bool),
169
+ Type.void),
170
+ Type.void),
171
+ Type.unknown),
172
+ Type.void),
173
+ Type.function(Type.unknown, [Type.value], Type.bool)),
174
+ "R2CRewriter" => :same,
175
+ "Ruby2RubyC" => "static VALUE\nrrc_c_bools(VALUE self, VALUE arg1) {\nif (RTEST(NIL_P(arg1))) {\nreturn Qfalse;\n} else {\nreturn Qtrue;\n}\n}",
176
+ },
177
+
178
+ # TODO: move all call tests here
179
+ "call_arglist" => {
180
+ "ParseTree" => [:fcall, :puts, [:array, [:lit, 42]]],
181
+ "Rewriter" => s(:call, nil, :puts, s(:arglist, s(:lit, 42))),
182
+ "TypeChecker" => :skip,
183
+ "R2CRewriter" => :skip,
184
+ "Ruby2RubyC" => :skip,
185
+ },
186
+
187
+ "call_attrasgn" => {
188
+ "ParseTree" => [:attrasgn, [:lit, 42], :method=, [:array, [:lvar, :y]]],
189
+ "Rewriter" => s(:call, s(:lit, 42), :method=, s(:arglist, s(:lvar, :y))),
190
+ "TypeChecker" => :skip,
191
+ "R2CRewriter" => :skip,
192
+ "Ruby2RubyC" => :skip,
193
+ },
194
+
195
+ "call_self" => {
196
+ "ParseTree" => [:call, [:self], :method],
197
+ "Rewriter" => s(:call, s(:lvar, :self), :method, nil),
198
+ "TypeChecker" => :skip,
199
+ "R2CRewriter" => :skip,
200
+ "Ruby2RubyC" => :skip,
201
+ },
202
+
203
+ "case_stmt" => {
204
+ "ParseTree" => [:defn, :case_stmt,
205
+ [:scope,
206
+ [:block,
207
+ [:args],
208
+ [:lasgn, :var, [:lit, 2]],
209
+ [:lasgn, :result, [:str, ""]],
210
+ [:case,
211
+ [:lvar, :var],
212
+ [:when,
213
+ [:array, [:lit, 1]],
214
+ [:block,
215
+ [:fcall, :puts, [:array, [:str, "something"]]],
216
+ [:lasgn, :result, [:str, "red"]]]],
217
+ [:when,
218
+ [:array, [:lit, 2], [:lit, 3]],
219
+ [:lasgn, :result, [:str, "yellow"]]],
220
+ [:when, [:array, [:lit, 4]], nil],
221
+ [:lasgn, :result, [:str, "green"]]],
222
+ [:case,
223
+ [:lvar, :result],
224
+ [:when, [:array, [:str, "red"]], [:lasgn, :var, [:lit, 1]]],
225
+ [:when, [:array, [:str, "yellow"]], [:lasgn, :var, [:lit, 2]]],
226
+ [:when, [:array, [:str, "green"]], [:lasgn, :var, [:lit, 3]]],
227
+ nil],
228
+ [:return, [:lvar, :result]]]]],
229
+ "Rewriter" => s(:defn, :case_stmt,
230
+ s(:args),
231
+ s(:scope,
232
+ s(:block,
233
+ s(:lasgn, :var, s(:lit, 2)),
234
+ s(:lasgn, :result, s(:str, "")),
235
+ s(:if,
236
+ s(:call,
237
+ s(:lvar, :var),
238
+ :===,
239
+ s(:arglist, s(:lit, 1))),
240
+ s(:block,
241
+ s(:call,
242
+ nil,
243
+ :puts,
244
+ s(:arglist, s(:str, "something"))),
245
+ s(:lasgn, :result, s(:str, "red"))),
246
+ s(:if,
247
+ s(:or,
248
+ s(:call,
249
+ s(:lvar, :var),
250
+ :===,
251
+ s(:arglist, s(:lit, 2))),
252
+ s(:call,
253
+ s(:lvar, :var),
254
+ :===,
255
+ s(:arglist, s(:lit, 3)))),
256
+ s(:lasgn, :result, s(:str, "yellow")),
257
+ s(:if,
258
+ s(:call,
259
+ s(:lvar, :var),
260
+ :===,
261
+ s(:arglist, s(:lit, 4))),
262
+ nil,
263
+ s(:lasgn, :result, s(:str, "green"))))),
264
+ s(:if,
265
+ s(:call,
266
+ s(:lvar, :result),
267
+ :===,
268
+ s(:arglist, s(:str, "red"))),
269
+ s(:lasgn, :var, s(:lit, 1)),
270
+ s(:if,
271
+ s(:call,
272
+ s(:lvar, :result),
273
+ :===,
274
+ s(:arglist, s(:str, "yellow"))),
275
+ s(:lasgn, :var, s(:lit, 2)),
276
+ s(:if,
277
+ s(:call,
278
+ s(:lvar, :result),
279
+ :===,
280
+ s(:arglist, s(:str, "green"))),
281
+ s(:lasgn, :var, s(:lit, 3)),
282
+ nil))),
283
+ s(:return, s(:lvar, :result))))),
284
+ "TypeChecker" => t(:defn, :case_stmt,
285
+ t(:args),
286
+ t(:scope,
287
+ t(:block,
288
+ t(:lasgn,
289
+ :var,
290
+ t(:lit, 2, Type.long),
291
+ Type.long),
292
+ t(:lasgn,
293
+ :result,
294
+ t(:str, "", Type.str),
295
+ Type.str),
296
+ t(:if,
297
+ t(:call,
298
+ t(:lvar, :var, Type.long),
299
+ :case_equal_long,
300
+ t(:arglist, t(:lit, 1, Type.long)),
301
+ Type.bool),
302
+ t(:block,
303
+ t(:call,
304
+ nil,
305
+ :puts,
306
+ t(:arglist,
307
+ t(:str, "something", Type.str)),
308
+ Type.void),
309
+ t(:lasgn,
310
+ :result,
311
+ t(:str, "red", Type.str),
312
+ Type.str),
313
+ Type.str),
314
+ t(:if,
315
+ t(:or,
316
+ t(:call,
317
+ t(:lvar, :var, Type.long),
318
+ :case_equal_long,
319
+ t(:arglist, t(:lit, 2, Type.long)),
320
+ Type.bool),
321
+ t(:call,
322
+ t(:lvar, :var, Type.long),
323
+ :case_equal_long,
324
+ t(:arglist, t(:lit, 3, Type.long)),
325
+ Type.bool),
326
+ Type.bool),
327
+ t(:lasgn,
328
+ :result,
329
+ t(:str, "yellow", Type.str),
330
+ Type.str),
331
+ t(:if,
332
+ t(:call,
333
+ t(:lvar, :var, Type.long),
334
+ :case_equal_long,
335
+ t(:arglist, t(:lit, 4, Type.long)),
336
+ Type.bool),
337
+ nil,
338
+ t(:lasgn,
339
+ :result,
340
+ t(:str, "green", Type.str),
341
+ Type.str),
342
+ Type.str),
343
+ Type.str),
344
+ Type.str),
345
+ t(:if,
346
+ t(:call,
347
+ t(:lvar, :result, Type.str),
348
+ :case_equal_str,
349
+ t(:arglist, t(:str, "red", Type.str)),
350
+ Type.bool),
351
+ t(:lasgn, :var, t(:lit, 1, Type.long), Type.long),
352
+ t(:if,
353
+ t(:call,
354
+ t(:lvar, :result, Type.str),
355
+ :case_equal_str,
356
+ t(:arglist, t(:str, "yellow", Type.str)),
357
+ Type.bool),
358
+ t(:lasgn, :var, t(:lit, 2, Type.long), Type.long),
359
+ t(:if,
360
+ t(:call,
361
+ t(:lvar, :result, Type.str),
362
+ :case_equal_str,
363
+ t(:arglist,
364
+ t(:str, "green", Type.str)),
365
+ Type.bool),
366
+ t(:lasgn,
367
+ :var,
368
+ t(:lit, 3, Type.long),
369
+ Type.long),
370
+ nil,
371
+ Type.long),
372
+ Type.long),
373
+ Type.long),
374
+ t(:return,
375
+ t(:lvar, :result, Type.str),
376
+ Type.void),
377
+ Type.unknown),
378
+ Type.void),
379
+ Type.function(Type.unknown, [], Type.str)),
380
+ "R2CRewriter" => :same,
381
+ # HACK: I don't like the semis after the if blocks, but it is a compromise right now
382
+ "Ruby2RubyC" => "static VALUE
383
+ rrc_c_case_stmt(VALUE self) {
384
+ VALUE result;
385
+ VALUE var;
386
+ var = LONG2FIX(2);
387
+ result = rb_str_new2(\"\");
388
+ if (RTEST(rb_funcall(var, rb_intern(\"case_equal_long\"), 1, LONG2FIX(1)))) {
389
+ rb_funcall(self, rb_intern(\"puts\"), 1, rb_str_new2(\"something\"));
390
+ result = rb_str_new2(\"red\");
391
+ } else {
392
+ if (RTEST(RTEST(rb_funcall(var, rb_intern(\"case_equal_long\"), 1, LONG2FIX(2))) || RTEST(rb_funcall(var, rb_intern(\"case_equal_long\"), 1, LONG2FIX(3))))) {
393
+ result = rb_str_new2(\"yellow\");
394
+ } else {
395
+ if (RTEST(rb_funcall(var, rb_intern(\"case_equal_long\"), 1, LONG2FIX(4)))) {
396
+ ;
397
+ } else {
398
+ result = rb_str_new2(\"green\");
399
+ }
400
+ }
401
+ };
402
+ if (RTEST(rb_funcall(result, rb_intern(\"case_equal_str\"), 1, rb_str_new2(\"red\")))) {
403
+ var = LONG2FIX(1);
404
+ } else {
405
+ if (RTEST(rb_funcall(result, rb_intern(\"case_equal_str\"), 1, rb_str_new2(\"yellow\")))) {
406
+ var = LONG2FIX(2);
407
+ } else {
408
+ if (RTEST(rb_funcall(result, rb_intern(\"case_equal_str\"), 1, rb_str_new2(\"green\")))) {
409
+ var = LONG2FIX(3);
410
+ }
411
+ }
412
+ };
413
+ return result;
414
+ }",
415
+ },
416
+
417
+ "conditional1" => {
418
+ "ParseTree" => [:if, [:call, [:lit, 42], :==, [:array, [:lit, 0]]], [:return, [:lit, 1]], nil],
419
+ "Rewriter" => s(:if, s(:call, s(:lit, 42), :==, s(:arglist, s(:lit, 0))), s(:return, s(:lit, 1)), nil),
420
+ "TypeChecker" => t(:if,
421
+ t(:call, t(:lit, 42, Type.long), :==,
422
+ t(:arglist, t(:lit, 0, Type.long)),
423
+ Type.bool),
424
+ t(:return, t(:lit, 1, Type.long), Type.void),
425
+ nil,
426
+ Type.void),
427
+ "R2CRewriter" => t(:if,
428
+ t(:call, t(:lit, 42, Type.long), :==,
429
+ t(:arglist, t(:lit, 0, Type.long)),
430
+ Type.bool),
431
+ t(:return, t(:lit, 1, Type.long), Type.void),
432
+ nil,
433
+ Type.void),
434
+ "Ruby2RubyC" => "if (RTEST(rb_funcall(LONG2FIX(42), rb_intern(\"==\"), 1, LONG2FIX(0)))) {\nreturn LONG2FIX(1);\n}",
435
+ },
436
+
437
+ "conditional2" => {
438
+ "ParseTree" => [:if, [:call, [:lit, 42], :==, [:array, [:lit, 0]]], nil, [:return, [:lit, 2]]],
439
+ "Rewriter" => s(:if,
440
+ s(:call, s(:lit, 42),
441
+ :==, s(:arglist, s(:lit, 0))),
442
+ nil,
443
+ s(:return, s(:lit, 2))),
444
+ "TypeChecker" => t(:if,
445
+ t(:call,
446
+ t(:lit, 42, Type.long),
447
+ :==,
448
+ t(:arglist,
449
+ t(:lit, 0, Type.long)),
450
+ Type.bool),
451
+ nil,
452
+ t(:return, t(:lit, 2, Type.long), Type.void),
453
+ Type.void),
454
+ "R2CRewriter" => :same,
455
+ "Ruby2RubyC" => "if (RTEST(rb_funcall(LONG2FIX(42), rb_intern(\"==\"), 1, LONG2FIX(0)))) {\n;\n} else {\nreturn LONG2FIX(2);\n}",
456
+ },
457
+
458
+ "conditional3" => {
459
+ "ParseTree" => [:if, [:call, [:lit, 42], :==, [:array, [:lit, 0]]],
460
+ [:return, [:lit, 3]],
461
+ [:return, [:lit, 4]]],
462
+ "Rewriter" => s(:if,
463
+ s(:call,
464
+ s(:lit, 42),
465
+ :==,
466
+ s(:arglist, s(:lit, 0))),
467
+ s(:return, s(:lit, 3)),
468
+ s(:return, s(:lit, 4))),
469
+ "TypeChecker" => t(:if,
470
+ t(:call,
471
+ t(:lit, 42, Type.long),
472
+ :==,
473
+ t(:arglist,
474
+ t(:lit, 0, Type.long)),
475
+ Type.bool),
476
+ t(:return,
477
+ t(:lit, 3, Type.long),
478
+
479
+ Type.void),
480
+ t(:return,
481
+ t(:lit, 4, Type.long),
482
+ Type.void),
483
+ Type.void),
484
+ "R2CRewriter" => :same,
485
+ "Ruby2RubyC" => "if (RTEST(rb_funcall(LONG2FIX(42), rb_intern(\"==\"), 1, LONG2FIX(0)))) {\nreturn LONG2FIX(3);\n} else {\nreturn LONG2FIX(4);\n}",
486
+ },
487
+
488
+ "conditional4" => {
489
+ "ParseTree" => [:if,
490
+ [:call, [:lit, 42], :==, [:array, [:lit, 0]]],
491
+ [:return, [:lit, 2]],
492
+ [:if,
493
+ [:call, [:lit, 42], :<, [:array, [:lit, 0]]],
494
+ [:return, [:lit, 3]],
495
+ [:return, [:lit, 4]]]],
496
+ "Rewriter" => s(:if,
497
+ s(:call,
498
+ s(:lit, 42),
499
+ :==,
500
+ s(:arglist, s(:lit, 0))),
501
+ s(:return, s(:lit, 2)),
502
+ s(:if,
503
+ s(:call,
504
+ s(:lit, 42),
505
+ :<,
506
+ s(:arglist, s(:lit, 0))),
507
+ s(:return, s(:lit, 3)),
508
+ s(:return, s(:lit, 4)))),
509
+ "TypeChecker" => t(:if,
510
+ t(:call,
511
+ t(:lit, 42, Type.long),
512
+ :==,
513
+ t(:arglist,
514
+ t(:lit, 0, Type.long)),
515
+ Type.bool),
516
+ t(:return,
517
+ t(:lit, 2, Type.long),
518
+ Type.void),
519
+ t(:if,
520
+ t(:call,
521
+ t(:lit, 42, Type.long),
522
+ :<,
523
+ t(:arglist,
524
+ t(:lit, 0, Type.long)),
525
+ Type.bool),
526
+ t(:return,
527
+ t(:lit, 3, Type.long),
528
+ Type.void),
529
+ t(:return,
530
+ t(:lit, 4, Type.long),
531
+ Type.void),
532
+ Type.void),
533
+ Type.void),
534
+ "R2CRewriter" => :same,
535
+ "Ruby2RubyC" => "if (RTEST(rb_funcall(LONG2FIX(42), rb_intern(\"==\"), 1, LONG2FIX(0)))) {\nreturn LONG2FIX(2);\n} else {\nif (RTEST(rb_funcall(LONG2FIX(42), rb_intern(\"<\"), 1, LONG2FIX(0)))) {\nreturn LONG2FIX(3);\n} else {\nreturn LONG2FIX(4);\n}\n}",
536
+ },
537
+
538
+ "defn_empty" => {
539
+ "ParseTree" => [:defn, :empty, [:scope, [:block, [:args], [:nil]]]],
540
+ "Rewriter" => s(:defn, :empty,
541
+ s(:args), s(:scope, s(:block, s(:nil)))),
542
+ "TypeChecker" => t(:defn, :empty,
543
+ t(:args),
544
+ t(:scope,
545
+ t(:block,
546
+ t(:nil, Type.value),
547
+ Type.unknown),
548
+ Type.void),
549
+ Type.function(Type.unknown, [], Type.void)),
550
+ "R2CRewriter" => :same,
551
+ "Ruby2RubyC" => "static VALUE\nrrc_c_empty(VALUE self) {\nQnil;\n}",
552
+ },
553
+
554
+ "defn_fbody" => {
555
+ "ParseTree" => [:defn, :aliased,
556
+ [:fbody,
557
+ [:scope,
558
+ [:block,
559
+ [:args],
560
+ [:fcall, :puts, [:array, [:lit, 42]]]]]]],
561
+ "Rewriter" => s(:defn, :aliased,
562
+ s(:args),
563
+ s(:scope,
564
+ s(:block,
565
+ s(:call, nil, :puts, s(:arglist, s(:lit, 42)))))),
566
+ "TypeChecker" => :skip,
567
+ "R2CRewriter" => :skip,
568
+ "Ruby2RubyC" => :skip,
569
+ },
570
+
571
+ "dmethod_added" => {
572
+ "ParseTree" => [:defn,
573
+ :dmethod_added,
574
+ [:dmethod,
575
+ :bmethod_maker,
576
+ [:scope,
577
+ [:block,
578
+ [:args],
579
+ [:iter,
580
+ [:fcall, :define_method, [:array, [:lit, :bmethod_added]]],
581
+ [:dasgn_curr, :x],
582
+ [:call, [:dvar, :x], :+, [:array, [:lit, 1]]]]]]]],
583
+ "Rewriter" => s(:defn,
584
+ :dmethod_added,
585
+ s(:args, :x),
586
+ s(:scope,
587
+ s(:block,
588
+ s(:call, s(:lvar, :x), :+,
589
+ s(:arglist, s(:lit, 1)))))),
590
+ "TypeChecker" => :skip,
591
+ "R2CRewriter" => :skip,
592
+ "Ruby2RubyC" => :skip,
593
+ },
594
+
595
+ "global" => {
596
+ "ParseTree" => [:gvar, :$stderr],
597
+ "Rewriter" => s(:gvar, :$stderr),
598
+ # TODO: test s(:gvar, :$stderr) != t(:gvar, $stderr, Type.file)
599
+ "TypeChecker" => t(:gvar, :$stderr, Type.file),
600
+ "R2CRewriter" => :same,
601
+ "Ruby2RubyC" => "stderr",
602
+ },
603
+
604
+ "interpolated" => {
605
+ "ParseTree" => [:dstr,
606
+ "var is ", [:lvar, :argl], [:str, ". So there."]],
607
+ "Rewriter" => s(:dstr,
608
+ "var is ", s(:lvar, :argl), s(:str, ". So there.")),
609
+ "TypeChecker" => t(:dstr,
610
+ "var is ",
611
+ t(:lvar, :argl, Type.long),
612
+ t(:str, ". So there.", Type.str),
613
+ Type.str),
614
+ "R2CRewriter" => :same,
615
+ "Ruby2RubyC" => :unsupported,
616
+ },
617
+
618
+ "iteration1" => {
619
+ "ParseTree" => [:iter,
620
+ [:call, [:lvar, :arrayl], :each],
621
+ [:dasgn_curr, :x],
622
+ [:fcall, :puts, [:arrayl, [:call, [:dvar, :x], :to_s]]]],
623
+ "Rewriter" => s(:iter,
624
+ s(:call,
625
+ s(:lvar, :arrayl),
626
+ :each,
627
+ nil),
628
+ s(:dasgn_curr, :x),
629
+ s(:call,
630
+ nil,
631
+ :puts,
632
+ s(:arglist,
633
+ s(:call,
634
+ s(:dvar, :x),
635
+ :to_s,
636
+ nil)))),
637
+ "TypeChecker" => t(:iter,
638
+ t(:call,
639
+ t(:lvar, :arrayl, Type.long_list),
640
+ :each,
641
+ nil, Type.unknown),
642
+ t(:dasgn_curr, :x, Type.long),
643
+ t(:call,
644
+ nil,
645
+ :puts,
646
+ t(:arglist,
647
+ t(:call,
648
+ t(:dvar, :x, Type.long),
649
+ :to_s,
650
+ nil,
651
+ Type.str)),
652
+ Type.void),
653
+ Type.void),
654
+ "R2CRewriter" => :same,
655
+ "Ruby2RubyC" => "unsigned long index_x;\nfor (index_x = 0; index_x < arrayl.length; ++index_x) {\nVALUE x = arrayl.contents[index_x];\nrb_funcall(self, rb_intern(\"puts\"), 1, rb_funcall(x, rb_intern(\"to_s\"), 0));\n}",
656
+ },
657
+
658
+ "iteration2" => {
659
+ "ParseTree" => [:iter,
660
+ [:call, [:lvar, :arrays], :each],
661
+ [:dasgn_curr, :x],
662
+ [:fcall, :puts, [:arrays, [:dvar, :x]]]],
663
+ "Rewriter" => s(:iter,
664
+ s(:call, s(:lvar, :arrays), :each, nil),
665
+ s(:dasgn_curr, :x),
666
+ s(:call, nil, :puts, s(:arglist, s(:dvar, :x)))),
667
+ "TypeChecker" => t(:iter,
668
+ t(:call,
669
+ t(:lvar, :arrays, Type.str_list),
670
+ :each,
671
+ nil, Type.unknown),
672
+ t(:dasgn_curr, :x, Type.str),
673
+ t(:call, nil, :puts,
674
+ t(:arglist, t(:dvar, :x, Type.str)),
675
+ Type.void),
676
+ Type.void),
677
+ "R2CRewriter" => :same,
678
+ "Ruby2RubyC" => "unsigned long index_x;\nfor (index_x = 0; index_x < arrays.length; ++index_x) {\nVALUE x = arrays.contents[index_x];\nrb_funcall(self, rb_intern(\"puts\"), 1, x);\n}",
679
+ },
680
+
681
+ "iteration3" => {
682
+ "ParseTree" => [:iter,
683
+ [:call, [:lvar, :arrayl], :each],
684
+ [:dasgn_curr, :x],
685
+ [:iter,
686
+ [:call, [:lvar, :arrayl2], :each],
687
+ [:dasgn_curr, :y],
688
+ [:block,
689
+ [:fcall, :puts, [:array, [:call, [:dvar, :x], :to_s]]],
690
+ [:fcall, :puts, [:array, [:call, [:dvar, :y], :to_s]]]]]],
691
+ "Rewriter" => s(:iter, s(:call, s(:lvar, :arrayl), :each, nil),
692
+ s(:dasgn_curr, :x),
693
+ s(:iter,
694
+ s(:call, s(:lvar, :arrayl2), :each, nil),
695
+ s(:dasgn_curr, :y),
696
+ s(:block,
697
+ s(:call,
698
+ nil,
699
+ :puts,
700
+ s(:arglist, s(:call, s(:dvar, :x), :to_s, nil))),
701
+ s(:call,
702
+ nil,
703
+ :puts,
704
+ s(:arglist,
705
+ s(:call, s(:dvar, :y), :to_s, nil)))))),
706
+ "TypeChecker" => t(:iter,
707
+ t(:call,
708
+ t(:lvar, :arrayl, Type.long_list),
709
+ :each, nil, Type.unknown),
710
+ t(:dasgn_curr, :x, Type.long),
711
+ t(:iter,
712
+ t(:call,
713
+ t(:lvar, :arrayl2, Type.long_list),
714
+ :each, nil, Type.unknown),
715
+ t(:dasgn_curr, :y, Type.long),
716
+ t(:block,
717
+ t(:call, nil, :puts,
718
+ t(:arglist,
719
+ t(:call,
720
+ t(:dvar, :x, Type.long),
721
+ :to_s, nil, Type.str)),
722
+ Type.void),
723
+ t(:call,
724
+ nil,
725
+ :puts,
726
+ t(:arglist,
727
+ t(:call,
728
+ t(:dvar, :y, Type.long), :to_s,
729
+ nil, Type.str)),
730
+ Type.void),
731
+ Type.unknown),
732
+ Type.void),
733
+ Type.void),
734
+ "R2CRewriter" => :same,
735
+ "Ruby2RubyC" => "unsigned long index_x;\nfor (index_x = 0; index_x < arrayl.length; ++index_x) {\nVALUE x = arrayl.contents[index_x];\nunsigned long index_y;\nfor (index_y = 0; index_y < arrayl2.length; ++index_y) {\nVALUE y = arrayl2.contents[index_y];\nrb_funcall(self, rb_intern(\"puts\"), 1, rb_funcall(x, rb_intern(\"to_s\"), 0));\nrb_funcall(self, rb_intern(\"puts\"), 1, rb_funcall(y, rb_intern(\"to_s\"), 0));\n}\n}",
736
+ },
737
+
738
+ "iteration4" => {
739
+ "ParseTree" => [:iter,
740
+ [:call, [:lit, 1], :upto, [:array, [:lit, 3]]],
741
+ [:dasgn_curr, :n],
742
+ [:fcall, :puts, [:array, [:call, [:dvar, :n], :to_s]]]],
743
+ "Rewriter" => s(:dummy,
744
+ s(:lasgn, :n, s(:lit, 1)),
745
+ s(:while,
746
+ s(:call, s(:lvar, :n), :<=, s(:arglist, s(:lit, 3))),
747
+ s(:block,
748
+ s(:call,
749
+ nil,
750
+ :puts,
751
+ s(:arglist, s(:call, s(:lvar, :n), :to_s, nil))),
752
+ s(:lasgn, :n,
753
+ s(:call, s(:lvar, :n),
754
+ :+,
755
+ s(:arglist, s(:lit, 1))))), true)),
756
+ "TypeChecker" => t(:dummy, t(:lasgn, :n, t(:lit, 1, Type.long), Type.long),
757
+ t(:while,
758
+ t(:call,
759
+ t(:lvar, :n, Type.long),
760
+ :<=,
761
+ t(:arglist, t(:lit, 3, Type.long)), Type.bool),
762
+ t(:block,
763
+ t(:call, nil, :puts,
764
+ t(:arglist,
765
+ t(:call,
766
+ t(:lvar, :n, Type.long),
767
+ :to_s,
768
+ nil, Type.str)), Type.void),
769
+ t(:lasgn, :n,
770
+ t(:call,
771
+ t(:lvar, :n, Type.long),
772
+ :+,
773
+ t(:arglist,
774
+ t(:lit,
775
+ 1, Type.long)),
776
+ Type.long), Type.long), Type.unknown), true)),
777
+ "R2CRewriter" => :same,
778
+ "Ruby2RubyC" => "n = LONG2FIX(1);
779
+ while (RTEST(rb_funcall(n, rb_intern(\"<=\"), 1, LONG2FIX(3)))) {
780
+ rb_funcall(self, rb_intern(\"puts\"), 1, rb_funcall(n, rb_intern(\"to_s\"), 0));
781
+ n = rb_funcall(n, rb_intern(\"+\"), 1, LONG2FIX(1));
782
+ }",
783
+ },
784
+
785
+ "iteration5" => {
786
+ "ParseTree" => [:iter,
787
+ [:call, [:lit, 3], :downto, [:array, [:lit, 1]]],
788
+ [:dasgn_curr, :n],
789
+ [:fcall, :puts, [:array, [:call, [:dvar, :n], :to_s]]]],
790
+ "Rewriter" => s(:dummy, s(:lasgn, :n, s(:lit, 3)), s(:while,
791
+ s(:call, s(:lvar, :n), :>=, s(:arglist, s(:lit, 1))),
792
+ s(:block,
793
+ s(:call, nil, :puts,
794
+ s(:arglist, s(:call, s(:lvar, :n), :to_s, nil))),
795
+ s(:lasgn, :n, s(:call, s(:lvar, :n),
796
+ :-, s(:arglist, s(:lit, 1))))), true)),
797
+ "TypeChecker" => t(:dummy,
798
+ t(:lasgn, :n, t(:lit, 3, Type.long), Type.long),
799
+ t(:while,
800
+ t(:call,
801
+ t(:lvar, :n, Type.long),
802
+ :>=,
803
+ t(:arglist, t(:lit, 1, Type.long)), Type.bool),
804
+ t(:block,
805
+ t(:call, nil, :puts,
806
+ t(:arglist,
807
+ t(:call,
808
+ t(:lvar, :n, Type.long),
809
+ :to_s,
810
+ nil, Type.str)), Type.void),
811
+ t(:lasgn, :n,
812
+ t(:call,
813
+ t(:lvar, :n, Type.long),
814
+ :-,
815
+ t(:arglist, t(:lit, 1, Type.long)),
816
+ Type.long),
817
+ Type.long),
818
+ Type.unknown), true)),
819
+ "R2CRewriter" => :same,
820
+ "Ruby2RubyC" => "n = LONG2FIX(3);
821
+ while (RTEST(rb_funcall(n, rb_intern(\">=\"), 1, LONG2FIX(1)))) {
822
+ rb_funcall(self, rb_intern(\"puts\"), 1, rb_funcall(n, rb_intern(\"to_s\"), 0));
823
+ n = rb_funcall(n, rb_intern(\"-\"), 1, LONG2FIX(1));
824
+ }",
825
+ },
826
+
827
+ "iteration6" => {
828
+ "ParseTree" => [:while, [:call, [:lvar, :argl],
829
+ :>=, [:arglist, [:lit, 1]]], [:block,
830
+ [:call, nil, :puts, [:arglist, [:str, "hello"]]],
831
+ [:lasgn,
832
+ :argl,
833
+ [:call, [:lvar, :argl],
834
+ :-, [:arglist, [:lit, 1]]]]], true],
835
+ "Rewriter" => s(:while,
836
+ s(:call, s(:lvar, :argl),
837
+ :>=, s(:arglist, s(:lit, 1))),
838
+ s(:block,
839
+ s(:call, nil, :puts, s(:arglist, s(:str, "hello"))),
840
+ s(:lasgn,
841
+ :argl,
842
+ s(:call, s(:lvar, :argl),
843
+ :-, s(:arglist, s(:lit, 1))))), true),
844
+ "TypeChecker" => t(:while,
845
+ t(:call, t(:lvar, :argl, Type.long),
846
+ :>=,
847
+ t(:arglist, t(:lit, 1, Type.long)), Type.bool),
848
+ t(:block,
849
+ t(:call, nil, :puts,
850
+ t(:arglist, t(:str, "hello", Type.str)),
851
+ Type.void),
852
+ t(:lasgn,
853
+ :argl,
854
+ t(:call, t(:lvar, :argl, Type.long),
855
+ :-,
856
+ t(:arglist, t(:lit, 1, Type.long)), Type.long),
857
+ Type.long),
858
+ Type.unknown), true),
859
+ "R2CRewriter" => :same,
860
+ "Ruby2RubyC" => "while (RTEST(rb_funcall(argl, rb_intern(\">=\"), 1, LONG2FIX(1)))) {
861
+ rb_funcall(self, rb_intern(\"puts\"), 1, rb_str_new2(\"hello\"));
862
+ argl = rb_funcall(argl, rb_intern(\"-\"), 1, LONG2FIX(1));
863
+ }",
864
+ },
865
+
866
+ # TODO: this might still be too much
867
+ "lasgn_call" => {
868
+ "ParseTree" => [:lasgn, :c, [:call, [:lit, 2], :+, [:arglist, [:lit, 3]]]],
869
+ "Rewriter" => s(:lasgn, :c, s(:call, s(:lit, 2), :+, s(:arglist, s(:lit, 3)))),
870
+ "TypeChecker" => t(:lasgn, :c,
871
+ t(:call,
872
+ t(:lit, 2, Type.long),
873
+ :+,
874
+ t(:arglist,
875
+ t(:lit, 3, Type.long)),
876
+ Type.long),
877
+ Type.long),
878
+ "R2CRewriter" => :same,
879
+ "Ruby2RubyC" => "c = rb_funcall(LONG2FIX(2), rb_intern(\"+\"), 1, LONG2FIX(3))",
880
+ },
881
+
882
+ "multi_args" => {
883
+ "ParseTree" => [:defn, :multi_args,
884
+ [:scope,
885
+ [:block,
886
+ [:args, :arg1, :arg2],
887
+ [:lasgn,
888
+ :arg3,
889
+ [:call,
890
+ [:call, [:lvar, :arg1], :*, [:array, [:lvar, :arg2]]],
891
+ :*,
892
+ [:array, [:lit, 7]]]],
893
+ [:fcall, :puts, [:array, [:call, [:lvar, :arg3], :to_s]]],
894
+ [:return, [:str, "foo"]]]]],
895
+ "Rewriter" => s(:defn, :multi_args,
896
+ s(:args, :arg1, :arg2),
897
+ s(:scope,
898
+ s(:block,
899
+ s(:lasgn, :arg3,
900
+ s(:call,
901
+ s(:call,
902
+ s(:lvar, :arg1),
903
+ :*,
904
+ s(:arglist, s(:lvar, :arg2))),
905
+ :*,
906
+ s(:arglist, s(:lit, 7)))),
907
+ s(:call,
908
+ nil,
909
+ :puts,
910
+ s(:arglist,
911
+ s(:call,
912
+ s(:lvar, :arg3),
913
+ :to_s,
914
+ nil))),
915
+ s(:return, s(:str, "foo"))))),
916
+ "TypeChecker" => t(:defn, :multi_args,
917
+ t(:args,
918
+ t(:arg1, Type.long),
919
+ t(:arg2, Type.long)),
920
+ t(:scope,
921
+ t(:block,
922
+ t(:lasgn,
923
+ :arg3,
924
+ t(:call,
925
+ t(:call,
926
+ t(:lvar, :arg1, Type.long),
927
+ :*,
928
+ t(:arglist,
929
+ t(:lvar,
930
+ :arg2,
931
+ Type.long)),
932
+ Type.long),
933
+ :*,
934
+ t(:arglist,
935
+ t(:lit, 7, Type.long)),
936
+ Type.long),
937
+ Type.long),
938
+ t(:call,
939
+ nil,
940
+ :puts,
941
+ t(:arglist,
942
+ t(:call,
943
+ t(:lvar, :arg3, Type.long),
944
+ :to_s,
945
+ nil,
946
+ Type.str)),
947
+ Type.void),
948
+ t(:return, t(:str, "foo", Type.str),
949
+ Type.void),
950
+ Type.unknown),
951
+ Type.void),
952
+ Type.function(Type.unknown,
953
+ [Type.long, Type.long], Type.str)),
954
+ "R2CRewriter" => :same,
955
+ "Ruby2RubyC" => "static VALUE\nrrc_c_multi_args(VALUE self, VALUE arg1, VALUE arg2) {\nVALUE arg3;\narg3 = rb_funcall(rb_funcall(arg1, rb_intern(\"*\"), 1, arg2), rb_intern(\"*\"), 1, LONG2FIX(7));\nrb_funcall(self, rb_intern(\"puts\"), 1, rb_funcall(arg3, rb_intern(\"to_s\"), 0));\nreturn rb_str_new2(\"foo\");\n}",
956
+ },
957
+
958
+ "vcall" => {
959
+ "ParseTree" => [:vcall, :method],
960
+ "Rewriter" => s(:call, nil, :method, nil),
961
+ "TypeChecker" => t(:call, nil, :method, nil, Type.unknown),
962
+ "R2CRewriter" => :same,
963
+ "Ruby2RubyC" => "rb_funcall(self, rb_intern(\"method\"), 0)",
964
+ },
965
+
966
+ "whiles" => {
967
+ "ParseTree" => [:defn,
968
+ :whiles,
969
+ [:scope,
970
+ [:block,
971
+ [:args],
972
+ [:while, [:false],
973
+ [:fcall, :puts, [:array, [:str, "false"]]], true],
974
+ [:while, [:false],
975
+ [:fcall, :puts, [:array, [:str, "true"]]], false]]]],
976
+ "Rewriter" => s(:defn,
977
+ :whiles,
978
+ s(:args),
979
+ s(:scope,
980
+ s(:block,
981
+ s(:while,
982
+ s(:false),
983
+ s(:call, nil, :puts, s(:arglist, s(:str, "false"))),
984
+ true),
985
+ s(:while,
986
+ s(:false),
987
+ s(:call, nil, :puts, s(:arglist, s(:str, "true"))),
988
+ false)))),
989
+ "TypeChecker" => t(:defn,
990
+ :whiles,
991
+ t(:args),
992
+ t(:scope,
993
+ t(:block,
994
+ t(:while,
995
+ t(:false, Type.bool),
996
+ t(:call,
997
+ nil,
998
+ :puts,
999
+ t(:arglist, t(:str, "false", Type.str)), Type.void),
1000
+ true),
1001
+ t(:while,
1002
+ t(:false, Type.bool),
1003
+ t(:call,
1004
+ nil,
1005
+ :puts,
1006
+ t(:arglist, t(:str, "true", Type.str)), Type.void),
1007
+ false),
1008
+ Type.unknown),
1009
+ Type.void),
1010
+ Type.function(Type.unknown, [], Type.void)),
1011
+ "R2CRewriter" => :same,
1012
+ "Ruby2RubyC" => "static VALUE
1013
+ rrc_c_whiles(VALUE self) {
1014
+ while (RTEST(Qfalse)) {
1015
+ rb_funcall(self, rb_intern(\"puts\"), 1, rb_str_new2(\"false\"))
1016
+ };
1017
+ {
1018
+ rb_funcall(self, rb_intern(\"puts\"), 1, rb_str_new2(\"true\"))
1019
+ } while (RTEST(Qfalse));
1020
+ }",
1021
+ },
1022
+
1023
+ "zarray" => {
1024
+ "ParseTree" => [:lasgn, :a, [:zarray]],
1025
+ "Rewriter" => s(:lasgn, :a, s(:array)),
1026
+ "TypeChecker" => t(:lasgn, :a, t(:array), Type.unknown_list),
1027
+ "R2CRewriter" => :same,
1028
+ # TODO: we need to do something w/ said array because this is dumb:
1029
+ # TODO: ewww
1030
+ "Ruby2RubyC" => "a = rb_ary_new()",
1031
+ },
1032
+
1033
+ }
1034
+
1035
+ @@testcases.each do |node, data|
1036
+ data.each do |key, val|
1037
+ if val == :same then
1038
+ prev_key = @@testcase_order[@@testcase_order.index(key)-1]
1039
+ data[key] = data[prev_key].deep_clone
1040
+ end
1041
+ end
1042
+ end
1043
+
1044
+ def self.inherited(c)
1045
+ output_name = c.name.to_s.sub(/^Test/, '')
1046
+ raise "Unknown class #{c}" unless @@testcase_order.include? output_name
1047
+ input_name = @@testcase_order[@@testcase_order.index(output_name)-1]
1048
+
1049
+ @@testcases.each do |node, data|
1050
+ next if data[input_name] == :skip
1051
+ next if data[output_name] == :skip
1052
+
1053
+ c.send(:define_method, "test_#{node}".intern) do
1054
+ flunk "Processor is nil" if processor.nil?
1055
+ assert data.has_key?(input_name), "Unknown input data"
1056
+ assert data.has_key?(output_name), "Unknown expected data"
1057
+ input = data[input_name].deep_clone
1058
+ expected = data[output_name].deep_clone
1059
+
1060
+ case expected
1061
+ when :unsupported then
1062
+ assert_raises(UnsupportedNodeError) do
1063
+ processor.process(input)
1064
+ end
1065
+ else
1066
+ assert_equal expected, processor.process(input)
1067
+ end
1068
+ end
1069
+ end
1070
+ end
1071
+
1072
+ def test_stoopid
1073
+ # do nothing - shuts up empty test class requirement
1074
+ end
1075
+
1076
+ end