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.
- data/History.txt +69 -0
- data/Makefile +49 -0
- data/Manifest.txt +98 -0
- data/README.txt +75 -0
- data/demo/char.rb +13 -0
- data/demo/factorial.rb +11 -0
- data/demo/hello.rb +11 -0
- data/demo/misc.rb +25 -0
- data/demo/newarray.rb +11 -0
- data/demo/strcat.rb +12 -0
- data/rewrite.rb +32 -0
- data/rewriter.rb +356 -0
- data/ruby_to_c.rb +680 -0
- data/support.rb +317 -0
- data/test_all.rb +9 -0
- data/test_extras.rb +143 -0
- data/test_rewriter.rb +292 -0
- data/test_ruby_to_c.rb +533 -0
- data/test_support.rb +525 -0
- data/test_type_checker.rb +838 -0
- data/test_typed_sexp_processor.rb +134 -0
- data/translate.rb +31 -0
- data/type.rb +33 -0
- data/type_checker.rb +922 -0
- data/typed_sexp_processor.rb +88 -0
- data/validate.sh +49 -0
- data/zcomparable.rb +300 -0
- metadata +74 -0
data/test_rewriter.rb
ADDED
@@ -0,0 +1,292 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
|
3
|
+
$TESTING = true
|
4
|
+
|
5
|
+
begin require 'rubygems' rescue LoadError end
|
6
|
+
require 'test/unit'
|
7
|
+
require 'rewriter'
|
8
|
+
require 'r2ctestcase'
|
9
|
+
require 'parse_tree'
|
10
|
+
|
11
|
+
class TestRewriter < R2CTestCase
|
12
|
+
|
13
|
+
def setup
|
14
|
+
@processor = Rewriter.new
|
15
|
+
@rewrite = Rewriter.new
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_process_call
|
19
|
+
input = [:call, [:lit, 1], :+, [:arglist, [:lit, 1]]]
|
20
|
+
expect = input.deep_clone
|
21
|
+
|
22
|
+
assert_equal expect, @rewrite.process(input)
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_process_defn_block
|
26
|
+
input = [:defn, :meth, [:scope, [:block, [:args], [:return, [:nil]]]]]
|
27
|
+
output = [:defn, :meth, [:args], [:scope, [:block, [:return, [:nil]]]]]
|
28
|
+
|
29
|
+
assert_equal output, @rewrite.process(input)
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_process_defn_ivar
|
33
|
+
input = [:defn, :name, [:ivar, :@name]]
|
34
|
+
output = [:defn, :name, [:args], [:scope, [:block, [:return, [:ivar, :@name]]]]]
|
35
|
+
|
36
|
+
assert_equal output, @rewrite.process(input)
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_process_defn_attrset
|
40
|
+
input = [:defn, :meth, [:attrset, :@name]]
|
41
|
+
output = [:defn, :meth, [:args, :arg], [:scope, [:block, [:return, [:iasgn, :@name, [:lvar, :arg]]]]]]
|
42
|
+
|
43
|
+
assert_equal output, @rewrite.process(input)
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_process_fcall
|
47
|
+
input = [:fcall, :puts, [:array, [:lit, 1]]]
|
48
|
+
expect = [:call, nil, :puts, [:arglist, [:lit, 1]]]
|
49
|
+
assert_equal expect, @rewrite.process(input)
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_process_vcall_2
|
53
|
+
input = [:vcall, :method]
|
54
|
+
output = [:call, nil, :method, nil]
|
55
|
+
|
56
|
+
assert_equal output, @rewrite.process(input)
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_process_case
|
60
|
+
input = [:case,
|
61
|
+
[:lvar, :var],
|
62
|
+
[:when, [:array, [:lit, 1]], [:str, "1"]],
|
63
|
+
[:when, [:array, [:lit, 2], [:lit, 3]], [:str, "2, 3"]],
|
64
|
+
[:when, [:array, [:lit, 4]], [:str, "4"]],
|
65
|
+
[:str, "else"]]
|
66
|
+
|
67
|
+
expected = [:if,
|
68
|
+
[:call,
|
69
|
+
[:lvar, :var],
|
70
|
+
:===,
|
71
|
+
[:arglist, [:lit, 1]]],
|
72
|
+
[:str, "1"],
|
73
|
+
[:if,
|
74
|
+
[:or,
|
75
|
+
[:call,
|
76
|
+
[:lvar, :var],
|
77
|
+
:===,
|
78
|
+
[:arglist, [:lit, 2]]],
|
79
|
+
[:call,
|
80
|
+
[:lvar, :var],
|
81
|
+
:===,
|
82
|
+
[:arglist, [:lit, 3]]]],
|
83
|
+
[:str, "2, 3"],
|
84
|
+
[:if,
|
85
|
+
[:call,
|
86
|
+
[:lvar, :var],
|
87
|
+
:===,
|
88
|
+
[:arglist, [:lit, 4]]],
|
89
|
+
[:str, "4"],
|
90
|
+
[:str, "else"]]]]
|
91
|
+
|
92
|
+
assert_equal expected, @rewrite.process(input)
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_process_case_2
|
96
|
+
input = [:case,
|
97
|
+
[:lvar, :var],
|
98
|
+
[:when, [:array, [:lit, 1]], [:lasgn, :ret, [:str, "1"]]],
|
99
|
+
[:when,
|
100
|
+
[:array, [:lit, 2], [:lit, 3], [:lit, 5]],
|
101
|
+
[:lasgn, :ret, [:str, "2, 3"]]],
|
102
|
+
[:when, [:array, [:lit, 4]], [:lasgn, :ret, [:str, "4"]]],
|
103
|
+
[:lasgn, :ret, [:str, "else"]]]
|
104
|
+
|
105
|
+
expected = s(:if,
|
106
|
+
s(:call,
|
107
|
+
s(:lvar, :var),
|
108
|
+
:===,
|
109
|
+
s(:arglist, s(:lit, 1))),
|
110
|
+
s(:lasgn, :ret, s(:str, "1")),
|
111
|
+
s(:if,
|
112
|
+
s(:or,
|
113
|
+
s(:call, s(:lvar, :var), :===, s(:arglist, s(:lit, 2))),
|
114
|
+
s(:or,
|
115
|
+
s(:call, s(:lvar, :var), :===, s(:arglist, s(:lit, 3))),
|
116
|
+
s(:call, s(:lvar, :var), :===, s(:arglist, s(:lit, 5))))),
|
117
|
+
s(:lasgn, :ret, s(:str, "2, 3")),
|
118
|
+
s(:if,
|
119
|
+
s(:call, s(:lvar, :var), :===, s(:arglist, s(:lit, 4))),
|
120
|
+
s(:lasgn, :ret, s(:str, "4")),
|
121
|
+
s(:lasgn, :ret, s(:str, "else")))))
|
122
|
+
|
123
|
+
assert_equal expected, @rewrite.process(input)
|
124
|
+
end
|
125
|
+
|
126
|
+
def test_process_iter
|
127
|
+
input = [:iter,
|
128
|
+
[:call, [:lit, 3], :downto, [:array, [:lit, 1]]],
|
129
|
+
[:dasgn_curr, :n],
|
130
|
+
[:fcall, :puts, [:array, [:call, [:dvar, :n], :to_s]]]]
|
131
|
+
expected = s(:dummy,
|
132
|
+
s(:lasgn, :n, s(:lit, 3)),
|
133
|
+
s(:while,
|
134
|
+
s(:call,
|
135
|
+
s(:lvar, :n),
|
136
|
+
:>=,
|
137
|
+
s(:arglist, s(:lit, 1))),
|
138
|
+
s(:block,
|
139
|
+
s(:call,
|
140
|
+
nil,
|
141
|
+
:puts,
|
142
|
+
s(:arglist,
|
143
|
+
s(:call,
|
144
|
+
s(:lvar, :n),
|
145
|
+
:to_s,
|
146
|
+
nil))),
|
147
|
+
s(:lasgn, :n, s(:call,
|
148
|
+
s(:lvar, :n),
|
149
|
+
:-,
|
150
|
+
s(:arglist, s(:lit, 1))))), true))
|
151
|
+
|
152
|
+
assert_equal expected, @rewrite.process(input)
|
153
|
+
end
|
154
|
+
|
155
|
+
def test_iter_downto_nested
|
156
|
+
input = [:block,
|
157
|
+
[:iter,
|
158
|
+
[:call, [:lvar, :n], :downto, [:array, [:lit, 0]]],
|
159
|
+
[:dasgn_curr, :i],
|
160
|
+
[:iter,
|
161
|
+
[:call, [:dvar, :i], :downto, [:array, [:lit, 0]]],
|
162
|
+
[:dasgn_curr, :j],
|
163
|
+
[:nil]]]]
|
164
|
+
|
165
|
+
expected = s(:block,
|
166
|
+
s(:dummy,
|
167
|
+
s(:lasgn, :i, s(:lvar, :n)),
|
168
|
+
s(:while,
|
169
|
+
s(:call, s(:lvar, :i), :>=,
|
170
|
+
s(:arglist, s(:lit, 0))),
|
171
|
+
s(:block,
|
172
|
+
s(:dummy,
|
173
|
+
s(:lasgn, :j, s(:lvar, :i)),
|
174
|
+
s(:while,
|
175
|
+
s(:call, s(:lvar, :j), :>=,
|
176
|
+
s(:arglist, s(:lit, 0))),
|
177
|
+
s(:block,
|
178
|
+
s(:nil),
|
179
|
+
s(:lasgn, :j,
|
180
|
+
s(:call, s(:lvar, :j), :-,
|
181
|
+
s(:arglist, s(:lit, 1))))), true)),
|
182
|
+
s(:lasgn, :i,
|
183
|
+
s(:call, s(:lvar, :i), :-,
|
184
|
+
s(:arglist, s(:lit, 1))))), true)))
|
185
|
+
|
186
|
+
assert_equal expected, @rewrite.process(input)
|
187
|
+
end
|
188
|
+
|
189
|
+
def test_iter_upto_nested
|
190
|
+
input = [:block,
|
191
|
+
[:iter,
|
192
|
+
[:call, [:lvar, :n], :upto, [:array, [:lit, 0]]],
|
193
|
+
[:dasgn_curr, :i],
|
194
|
+
[:iter,
|
195
|
+
[:call, [:dvar, :i], :upto, [:array, [:lit, 0]]],
|
196
|
+
[:dasgn_curr, :j],
|
197
|
+
[:nil]]]]
|
198
|
+
|
199
|
+
expected = s(:block,
|
200
|
+
s(:dummy,
|
201
|
+
s(:lasgn, :i, s(:lvar, :n)),
|
202
|
+
s(:while,
|
203
|
+
s(:call, s(:lvar, :i), :<=,
|
204
|
+
s(:arglist, s(:lit, 0))),
|
205
|
+
s(:block,
|
206
|
+
s(:dummy,
|
207
|
+
s(:lasgn, :j, s(:lvar, :i)),
|
208
|
+
s(:while,
|
209
|
+
s(:call, s(:lvar, :j), :<=,
|
210
|
+
s(:arglist, s(:lit, 0))),
|
211
|
+
s(:block,
|
212
|
+
s(:nil),
|
213
|
+
s(:lasgn, :j,
|
214
|
+
s(:call, s(:lvar, :j), :+,
|
215
|
+
s(:arglist, s(:lit, 1))))), true)),
|
216
|
+
s(:lasgn, :i,
|
217
|
+
s(:call, s(:lvar, :i), :+,
|
218
|
+
s(:arglist, s(:lit, 1))))), true)))
|
219
|
+
|
220
|
+
assert_equal expected, @rewrite.process(input)
|
221
|
+
end
|
222
|
+
|
223
|
+
def test_process_until
|
224
|
+
input = [:until,
|
225
|
+
[:call,
|
226
|
+
[:lvar, :a],
|
227
|
+
:==,
|
228
|
+
[:array, [:lvar, :b]]],
|
229
|
+
[:fcall,
|
230
|
+
:puts,
|
231
|
+
[:array, [:lit, 2]]],
|
232
|
+
true]
|
233
|
+
output = s(:while,
|
234
|
+
s(:not,
|
235
|
+
s(:call,
|
236
|
+
s(:lvar, :a),
|
237
|
+
:==,
|
238
|
+
s(:arglist, s(:lvar, :b)))),
|
239
|
+
s(:call,
|
240
|
+
nil,
|
241
|
+
:puts,
|
242
|
+
s(:arglist, s(:lit, 2))),
|
243
|
+
true)
|
244
|
+
assert_equal output, @rewrite.process(input)
|
245
|
+
end
|
246
|
+
|
247
|
+
def test_process_when
|
248
|
+
input = [:when, [:array, [:lit, 1]], [:str, "1"]]
|
249
|
+
|
250
|
+
expected = [:when, [[:lit, 1]], [:str, "1"]]
|
251
|
+
|
252
|
+
assert_equal expected, @rewrite.process(input)
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
class TestR2CRewriter < R2CTestCase
|
257
|
+
|
258
|
+
def setup
|
259
|
+
@processor = R2CRewriter.new
|
260
|
+
@rewrite = R2CRewriter.new
|
261
|
+
end
|
262
|
+
|
263
|
+
def test_process_call_rewritten
|
264
|
+
|
265
|
+
input = t(:call,
|
266
|
+
t(:str, "this", Type.str),
|
267
|
+
:+,
|
268
|
+
t(:array, t(:str, "that", Type.str)),
|
269
|
+
Type.str)
|
270
|
+
expected = t(:call,
|
271
|
+
nil,
|
272
|
+
:strcat,
|
273
|
+
t(:array,
|
274
|
+
t(:str, "this", Type.str),
|
275
|
+
t(:str, "that", Type.str)),
|
276
|
+
Type.str)
|
277
|
+
|
278
|
+
assert_equal expected, @rewrite.process(input)
|
279
|
+
end
|
280
|
+
|
281
|
+
def test_process_call_same
|
282
|
+
|
283
|
+
input = t(:call,
|
284
|
+
t(:lit, 1, Type.long),
|
285
|
+
:+,
|
286
|
+
t(:array, t(:lit, 2, Type.long)),
|
287
|
+
Type.long)
|
288
|
+
expected = input.deep_clone
|
289
|
+
|
290
|
+
assert_equal expected, @rewrite.process(input)
|
291
|
+
end
|
292
|
+
end
|
data/test_ruby_to_c.rb
ADDED
@@ -0,0 +1,533 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
|
3
|
+
$TESTING = true
|
4
|
+
|
5
|
+
require 'test/unit'
|
6
|
+
require 'ruby_to_c'
|
7
|
+
require 'r2ctestcase'
|
8
|
+
|
9
|
+
class TestTypeMap < Test::Unit::TestCase
|
10
|
+
|
11
|
+
def test_c_type_long
|
12
|
+
assert_equal "long", TypeMap.c_type(Type.long)
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_c_type_long_list
|
16
|
+
assert_equal "long_array", TypeMap.c_type(Type.long_list)
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_c_type_str
|
20
|
+
assert_equal "str", TypeMap.c_type(Type.str)
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_c_type_str_list
|
24
|
+
assert_equal "str_array", TypeMap.c_type(Type.str_list)
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_c_type_bool
|
28
|
+
assert_equal "VALUE", TypeMap.c_type(Type.bool)
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_c_type_void
|
32
|
+
assert_equal "void", TypeMap.c_type(Type.void)
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_c_type_float
|
36
|
+
assert_equal "double", TypeMap.c_type(Type.float)
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_c_type_symbol
|
40
|
+
assert_equal "symbol", TypeMap.c_type(Type.symbol)
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_c_type_value
|
44
|
+
assert_equal "VALUE", TypeMap.c_type(Type.value)
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_c_type_unknown
|
48
|
+
assert_equal "VALUE", TypeMap.c_type(Type.unknown)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class TestRubyToC < R2CTestCase
|
53
|
+
|
54
|
+
def setup
|
55
|
+
@ruby_to_c = RubyToC.new
|
56
|
+
@ruby_to_c.env.extend
|
57
|
+
@processor = @ruby_to_c
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_translator
|
61
|
+
Object.class_eval "class Suck; end"
|
62
|
+
input = [:class, :Suck, :Object,
|
63
|
+
[:defn, :something, [:scope, [:block, [:args], [:fcall, :"whaaa\?"]]]],
|
64
|
+
[:defn, :foo, [:scope, [:block, [:args], [:vcall, :something]]]]]
|
65
|
+
expected = "// class Suck\n\n// ERROR: NoMethodError: undefined method `[]=' for nil:NilClass\n\nvoid\nfoo() {\nsomething();\n}"
|
66
|
+
assert_equal expected, RubyToC.translator.process(input)
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_env
|
70
|
+
assert_not_nil @ruby_to_c.env
|
71
|
+
assert_kind_of Environment, @ruby_to_c.env
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_prototypes
|
75
|
+
assert_equal [], @ruby_to_c.prototypes
|
76
|
+
@ruby_to_c.process t(:defn,
|
77
|
+
:empty,
|
78
|
+
t(:args),
|
79
|
+
t(:scope),
|
80
|
+
Type.function([], Type.void))
|
81
|
+
|
82
|
+
assert_equal "void empty();\n", @ruby_to_c.prototypes.first
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_process_and
|
86
|
+
input = t(:and, t(:lit, 1, Type.long), t(:lit, 2, Type.long))
|
87
|
+
output = "1 && 2"
|
88
|
+
|
89
|
+
assert_equal output, @ruby_to_c.process(input)
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_process_args_normal
|
93
|
+
input = t(:args,
|
94
|
+
t(:foo, Type.long),
|
95
|
+
t(:bar, Type.long))
|
96
|
+
output = "(long foo, long bar)"
|
97
|
+
|
98
|
+
assert_equal output, @ruby_to_c.process(input)
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_process_args_empty
|
102
|
+
input = t(:args)
|
103
|
+
output = "()"
|
104
|
+
|
105
|
+
assert_equal output, @ruby_to_c.process(input)
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_process_array_empty
|
109
|
+
input = t(:array)
|
110
|
+
output = "[]"
|
111
|
+
|
112
|
+
assert_equal output, @ruby_to_c.process(input)
|
113
|
+
end
|
114
|
+
|
115
|
+
def test_process_array_single
|
116
|
+
input = t(:array,
|
117
|
+
t(:lvar, :arg1, Type.long))
|
118
|
+
output = "arg1"
|
119
|
+
|
120
|
+
assert_equal output, @ruby_to_c.process(input)
|
121
|
+
end
|
122
|
+
|
123
|
+
def test_process_array_multiple
|
124
|
+
input = t(:array,
|
125
|
+
t(:lvar, :arg1, Type.long),
|
126
|
+
t(:lvar, :arg2, Type.long))
|
127
|
+
output = "arg1, arg2"
|
128
|
+
|
129
|
+
assert_equal output, @ruby_to_c.process(input)
|
130
|
+
end
|
131
|
+
|
132
|
+
def test_process_call
|
133
|
+
input = t(:call, nil, :name, nil)
|
134
|
+
output = "name()"
|
135
|
+
|
136
|
+
assert_equal output, @ruby_to_c.process(input)
|
137
|
+
end
|
138
|
+
|
139
|
+
def test_process_call_lhs
|
140
|
+
input = t(:call, t(:lit, 1, Type.long), :name, nil)
|
141
|
+
output = "name(1)"
|
142
|
+
|
143
|
+
assert_equal output, @ruby_to_c.process(input)
|
144
|
+
end
|
145
|
+
|
146
|
+
def test_process_call_lhs_rhs
|
147
|
+
input = t(:call,
|
148
|
+
t(:lit, 1, Type.long),
|
149
|
+
:name,
|
150
|
+
t(:array, t(:str, "foo")))
|
151
|
+
output = "name(1, \"foo\")"
|
152
|
+
|
153
|
+
assert_equal output, @ruby_to_c.process(input)
|
154
|
+
end
|
155
|
+
|
156
|
+
def test_process_call_rhs
|
157
|
+
input = t(:call,
|
158
|
+
nil,
|
159
|
+
:name,
|
160
|
+
t(:array,
|
161
|
+
t(:str, "foo")))
|
162
|
+
output = "name(\"foo\")"
|
163
|
+
|
164
|
+
assert_equal output, @ruby_to_c.process(input)
|
165
|
+
end
|
166
|
+
|
167
|
+
def test_process_call_nil?
|
168
|
+
input = t(:call,
|
169
|
+
t(:lvar, :arg, Type.long),
|
170
|
+
:nil?,
|
171
|
+
nil)
|
172
|
+
output = "NIL_P(arg)"
|
173
|
+
|
174
|
+
assert_equal output, @ruby_to_c.process(input)
|
175
|
+
end
|
176
|
+
|
177
|
+
def test_process_call_operator
|
178
|
+
methods = t(:==, :<, :>, :-, :+, :*, :/, :%, :<=, :>=)
|
179
|
+
|
180
|
+
methods.each do |method|
|
181
|
+
input = t(:call,
|
182
|
+
t(:lit, 1, Type.long),
|
183
|
+
method,
|
184
|
+
t(:array, t(:lit, 2, Type.long)))
|
185
|
+
output = "1 #{method} 2"
|
186
|
+
|
187
|
+
assert_equal output, @ruby_to_c.process(input)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def test_process_block
|
192
|
+
input = t(:block, t(:return, t(:nil)))
|
193
|
+
output = "return Qnil;\n"
|
194
|
+
|
195
|
+
assert_equal output, @ruby_to_c.process(input)
|
196
|
+
end
|
197
|
+
|
198
|
+
def test_process_block_multiple
|
199
|
+
input = t(:block,
|
200
|
+
t(:str, "foo"),
|
201
|
+
t(:return, t(:nil)))
|
202
|
+
output = "\"foo\";\nreturn Qnil;\n"
|
203
|
+
|
204
|
+
assert_equal output, @ruby_to_c.process(input)
|
205
|
+
end
|
206
|
+
|
207
|
+
def test_process_dasgn_curr
|
208
|
+
input = t(:dasgn_curr, :x, Type.long)
|
209
|
+
output = "x"
|
210
|
+
|
211
|
+
assert_equal output, @ruby_to_c.process(input)
|
212
|
+
# HACK - see test_type_checker equivalent test
|
213
|
+
# assert_equal Type.long, @ruby_to_c.env.lookup("x")
|
214
|
+
end
|
215
|
+
|
216
|
+
# TODO: fix for 1.8.2
|
217
|
+
def test_process_defn
|
218
|
+
input = t(:defn,
|
219
|
+
:empty,
|
220
|
+
t(:args),
|
221
|
+
t(:scope),
|
222
|
+
Type.function([], Type.void))
|
223
|
+
output = "void\nempty() {\n}"
|
224
|
+
assert_equal output, @ruby_to_c.process(input)
|
225
|
+
|
226
|
+
assert_equal ["void empty();\n"], @ruby_to_c.prototypes
|
227
|
+
|
228
|
+
end
|
229
|
+
|
230
|
+
def test_process_defn_with_args_and_body
|
231
|
+
input = t(:defn, :empty,
|
232
|
+
t(:args,
|
233
|
+
t(:foo, Type.long),
|
234
|
+
t(:bar, Type.long)),
|
235
|
+
t(:scope,
|
236
|
+
t(:block,
|
237
|
+
t(:lit, 5, Type.long))),
|
238
|
+
Type.function([], Type.void))
|
239
|
+
output = "void\nempty(long foo, long bar) {\n5;\n}"
|
240
|
+
|
241
|
+
assert_equal output, @ruby_to_c.process(input)
|
242
|
+
end
|
243
|
+
|
244
|
+
def disabled_test_dstr
|
245
|
+
input = t(:dstr,
|
246
|
+
"var is ",
|
247
|
+
t(:lvar, :var),
|
248
|
+
t(:str, ". So there."))
|
249
|
+
output = "sprintf stuff goes here"
|
250
|
+
|
251
|
+
flunk "Way too hard right now"
|
252
|
+
assert_equal output, @ruby_to_c.process(input)
|
253
|
+
end
|
254
|
+
|
255
|
+
def test_process_dvar
|
256
|
+
input = t(:dvar, :dvar, Type.long)
|
257
|
+
output = "dvar"
|
258
|
+
|
259
|
+
assert_equal output, @ruby_to_c.process(input)
|
260
|
+
end
|
261
|
+
|
262
|
+
def test_process_false
|
263
|
+
input = t(:false)
|
264
|
+
output = "Qfalse"
|
265
|
+
|
266
|
+
assert_equal output, @ruby_to_c.process(input)
|
267
|
+
end
|
268
|
+
|
269
|
+
def test_process_gvar
|
270
|
+
input = t(:gvar, :$stderr, Type.long)
|
271
|
+
output = "stderr"
|
272
|
+
|
273
|
+
assert_equal output, @ruby_to_c.process(input)
|
274
|
+
assert_raises RuntimeError do
|
275
|
+
@ruby_to_c.process t(:gvar, :$some_gvar, Type.long)
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
def test_process_iasgn
|
280
|
+
input = t(:iasgn, :@blah, t(:lit, 42, Type.long), Type.long)
|
281
|
+
expected = "self->blah = 42"
|
282
|
+
|
283
|
+
assert_equal expected, @ruby_to_c.process(input)
|
284
|
+
end
|
285
|
+
|
286
|
+
def test_process_if
|
287
|
+
input = t(:if,
|
288
|
+
t(:call,
|
289
|
+
t(:lit, 1, Type.long),
|
290
|
+
:==,
|
291
|
+
t(:array, t(:lit, 2, Type.long))),
|
292
|
+
t(:str, "not equal"),
|
293
|
+
nil)
|
294
|
+
output = "if (1 == 2) {\n\"not equal\";\n}"
|
295
|
+
|
296
|
+
assert_equal output, @ruby_to_c.process(input)
|
297
|
+
end
|
298
|
+
|
299
|
+
def test_process_if_else
|
300
|
+
input = t(:if,
|
301
|
+
t(:call,
|
302
|
+
t(:lit, 1, Type.long),
|
303
|
+
:==,
|
304
|
+
t(:array, t(:lit, 2, Type.long))),
|
305
|
+
t(:str, "not equal"),
|
306
|
+
t(:str, "equal"))
|
307
|
+
output = "if (1 == 2) {\n\"not equal\";\n} else {\n\"equal\";\n}"
|
308
|
+
|
309
|
+
assert_equal output, @ruby_to_c.process(input)
|
310
|
+
end
|
311
|
+
|
312
|
+
def test_process_if_block
|
313
|
+
input = t(:if,
|
314
|
+
t(:call,
|
315
|
+
t(:lit, 1, Type.long),
|
316
|
+
:==,
|
317
|
+
t(:array, t(:lit, 2, Type.long))),
|
318
|
+
t(:block,
|
319
|
+
t(:lit, 5, Type.long),
|
320
|
+
t(:str, "not equal")),
|
321
|
+
nil)
|
322
|
+
output = "if (1 == 2) {\n5;\n\"not equal\";\n}"
|
323
|
+
|
324
|
+
assert_equal output, @ruby_to_c.process(input)
|
325
|
+
end
|
326
|
+
|
327
|
+
def test_process_iter
|
328
|
+
var_type = Type.long_list
|
329
|
+
input = t(:iter,
|
330
|
+
t(:call,
|
331
|
+
t(:lvar, :array, var_type),
|
332
|
+
:each,
|
333
|
+
nil),
|
334
|
+
t(:dasgn_curr, :x, Type.long),
|
335
|
+
t(:call,
|
336
|
+
nil,
|
337
|
+
:puts,
|
338
|
+
t(:array,
|
339
|
+
t(:call,
|
340
|
+
t(:dvar,
|
341
|
+
:x,
|
342
|
+
Type.long),
|
343
|
+
:to_s,
|
344
|
+
nil))))
|
345
|
+
output = "unsigned long index_x;
|
346
|
+
for (index_x = 0; index_x < array.length; ++index_x) {
|
347
|
+
long x = array.contents[index_x];
|
348
|
+
puts(to_s(x));
|
349
|
+
}"
|
350
|
+
|
351
|
+
assert_equal output, @ruby_to_c.process(input)
|
352
|
+
end
|
353
|
+
|
354
|
+
def test_process_ivar
|
355
|
+
@ruby_to_c.env.add :@blah, Type.long
|
356
|
+
input = t(:ivar, :@blah, Type.long)
|
357
|
+
expected = "self->blah"
|
358
|
+
|
359
|
+
assert_equal expected, @ruby_to_c.process(input)
|
360
|
+
end
|
361
|
+
|
362
|
+
def test_process_lasgn
|
363
|
+
input = t(:lasgn, :var, t(:str, "foo"), Type.str)
|
364
|
+
output = "var = \"foo\""
|
365
|
+
|
366
|
+
assert_equal output, @ruby_to_c.process(input)
|
367
|
+
end
|
368
|
+
|
369
|
+
def test_process_lasgn_array
|
370
|
+
input = t(:lasgn,
|
371
|
+
:var,
|
372
|
+
t(:array,
|
373
|
+
t(:str, "foo", Type.str),
|
374
|
+
t(:str, "bar", Type.str)),
|
375
|
+
Type.str_list)
|
376
|
+
output = "var.length = 2;
|
377
|
+
var.contents = (str*) malloc(sizeof(str) * var.length);
|
378
|
+
var.contents[0] = \"foo\";
|
379
|
+
var.contents[1] = \"bar\""
|
380
|
+
|
381
|
+
assert_equal output, @ruby_to_c.process(input)
|
382
|
+
end
|
383
|
+
|
384
|
+
def test_process_lit_float
|
385
|
+
input = t(:lit, 1.0, Type.float)
|
386
|
+
output = "1.0"
|
387
|
+
|
388
|
+
assert_equal output, @ruby_to_c.process(input)
|
389
|
+
end
|
390
|
+
|
391
|
+
def test_process_lit_long
|
392
|
+
input = t(:lit, 1, Type.long)
|
393
|
+
output = "1"
|
394
|
+
|
395
|
+
assert_equal output, @ruby_to_c.process(input)
|
396
|
+
end
|
397
|
+
|
398
|
+
def test_process_lit_sym
|
399
|
+
input = t(:lit, :sym, Type.symbol)
|
400
|
+
output = ":sym"
|
401
|
+
|
402
|
+
assert_equal output, @ruby_to_c.process(input)
|
403
|
+
end
|
404
|
+
|
405
|
+
def test_process_lvar
|
406
|
+
input = t(:lvar, :arg, Type.long)
|
407
|
+
output = "arg"
|
408
|
+
|
409
|
+
assert_equal output, @ruby_to_c.process(input)
|
410
|
+
end
|
411
|
+
|
412
|
+
def test_process_nil
|
413
|
+
input = t(:nil)
|
414
|
+
output = "Qnil"
|
415
|
+
|
416
|
+
assert_equal output, @ruby_to_c.process(input)
|
417
|
+
end
|
418
|
+
|
419
|
+
def test_process_not
|
420
|
+
input = t(:not, t(:true, Type.bool), Type.bool)
|
421
|
+
output = "!(Qtrue)"
|
422
|
+
|
423
|
+
assert_equal output, @ruby_to_c.process(input)
|
424
|
+
end
|
425
|
+
|
426
|
+
def test_process_or
|
427
|
+
input = t(:or, t(:lit, 1, Type.long), t(:lit, 2, Type.long))
|
428
|
+
output = "1 || 2"
|
429
|
+
|
430
|
+
assert_equal output, @ruby_to_c.process(input)
|
431
|
+
end
|
432
|
+
|
433
|
+
def test_process_return
|
434
|
+
input = t(:return, t(:nil))
|
435
|
+
output = "return Qnil"
|
436
|
+
|
437
|
+
assert_equal output, @ruby_to_c.process(input)
|
438
|
+
end
|
439
|
+
|
440
|
+
def test_process_str
|
441
|
+
input = t(:str, "foo", Type.str)
|
442
|
+
output = "\"foo\""
|
443
|
+
|
444
|
+
assert_equal output, @ruby_to_c.process(input)
|
445
|
+
end
|
446
|
+
|
447
|
+
def test_process_str_multi
|
448
|
+
input = t(:str, "foo
|
449
|
+
bar", Type.str)
|
450
|
+
output = "\"foo\\nbar\""
|
451
|
+
|
452
|
+
assert_equal output, @ruby_to_c.process(input)
|
453
|
+
end
|
454
|
+
|
455
|
+
def test_process_str_backslashed
|
456
|
+
input = t(:str, "foo\nbar", Type.str)
|
457
|
+
output = "\"foo\\nbar\""
|
458
|
+
|
459
|
+
assert_equal output, @ruby_to_c.process(input)
|
460
|
+
end
|
461
|
+
|
462
|
+
def test_process_scope
|
463
|
+
input = t(:scope,
|
464
|
+
t(:block,
|
465
|
+
t(:return, t(:nil))))
|
466
|
+
output = "{\nreturn Qnil;\n}"
|
467
|
+
|
468
|
+
assert_equal output, @ruby_to_c.process(input)
|
469
|
+
end
|
470
|
+
|
471
|
+
def test_process_scope_empty
|
472
|
+
input = t(:scope)
|
473
|
+
output = "{\n}"
|
474
|
+
|
475
|
+
assert_equal output, @ruby_to_c.process(input)
|
476
|
+
end
|
477
|
+
|
478
|
+
def test_process_scope_var_set
|
479
|
+
input = t(:scope, t(:block,
|
480
|
+
t(:lasgn, :arg,
|
481
|
+
t(:str, "declare me"),
|
482
|
+
Type.str),
|
483
|
+
t(:return, t(:nil))))
|
484
|
+
output = "{\nstr arg;\narg = \"declare me\";\nreturn Qnil;\n}"
|
485
|
+
|
486
|
+
assert_equal output, @ruby_to_c.process(input)
|
487
|
+
end
|
488
|
+
|
489
|
+
def test_process_true
|
490
|
+
input = t(:true)
|
491
|
+
output = "Qtrue"
|
492
|
+
|
493
|
+
assert_equal output, @ruby_to_c.process(input)
|
494
|
+
end
|
495
|
+
|
496
|
+
def test_process_unless
|
497
|
+
input = t(:if,
|
498
|
+
t(:call,
|
499
|
+
t(:lit, 1, Type.long),
|
500
|
+
:==,
|
501
|
+
t(:array, t(:lit, 2, Type.long))),
|
502
|
+
nil,
|
503
|
+
t(:str, "equal"))
|
504
|
+
output = "if (1 == 2) {\n;\n} else {\n\"equal\";\n}"
|
505
|
+
|
506
|
+
assert_equal output, @ruby_to_c.process(input)
|
507
|
+
end
|
508
|
+
|
509
|
+
def test_process_while
|
510
|
+
input = t(:while,
|
511
|
+
t(:call, t(:lvar, :n), :<=, t(:array, t(:lit, 3, Type.long))),
|
512
|
+
t(:block,
|
513
|
+
t(:call,
|
514
|
+
nil,
|
515
|
+
:puts,
|
516
|
+
t(:array,
|
517
|
+
t(:call,
|
518
|
+
t(:lvar, :n),
|
519
|
+
:to_s,
|
520
|
+
nil))),
|
521
|
+
t(:lasgn, :n,
|
522
|
+
t(:call,
|
523
|
+
t(:lvar, :n),
|
524
|
+
:+,
|
525
|
+
t(:array,
|
526
|
+
t(:lit, 1, Type.long))),
|
527
|
+
Type.long)), true) # NOTE Type.long needed but not used
|
528
|
+
|
529
|
+
expected = "while (n <= 3) {\nputs(to_s(n));\nn = n + 1;\n}"
|
530
|
+
|
531
|
+
assert_equal expected, @ruby_to_c.process(input)
|
532
|
+
end
|
533
|
+
end
|