ruby2c 1.0.0.6

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