fastruby 0.0.17 → 0.0.18
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/CHANGELOG +10 -0
- data/Rakefile +4 -2
- data/benchmarks/benchmark.rb +20 -44
- data/benchmarks/benchmark.rb~ +47 -0
- data/benchmarks/benchmark2.rb +19 -45
- data/benchmarks/benchmark2.rb~ +46 -0
- data/benchmarks/benchmark3.rb +19 -45
- data/benchmarks/benchmark3.rb~ +46 -0
- data/benchmarks/benchmark4.rb +30 -65
- data/benchmarks/benchmark4.rb~ +61 -0
- data/benchmarks/benchmark5.rb +25 -55
- data/benchmarks/benchmark5.rb~ +54 -0
- data/benchmarks/benchmark6.rb +19 -40
- data/benchmarks/benchmark6.rb~ +41 -0
- data/benchmarks/benchmark7.rb +23 -52
- data/benchmarks/benchmark7.rb~ +48 -0
- data/ext/fastruby_base/fastruby_base.inl +1 -0
- data/lib/fastruby/builder.rb +128 -76
- data/lib/fastruby/cache/cache.rb +9 -5
- data/lib/fastruby/fastruby_sexp.rb +18 -0
- data/lib/fastruby/inliner/inliner.rb +68 -0
- data/lib/fastruby/inliner/modules/call.rb +150 -0
- data/lib/fastruby/inliner/modules/recursive.rb +35 -0
- data/lib/fastruby/object.rb +17 -32
- data/lib/fastruby/reductor/modules/case.rb +49 -0
- data/lib/{fastruby.rb~ → fastruby/reductor/modules/for.rb} +11 -13
- data/lib/fastruby/reductor/modules/nontree.rb +31 -0
- data/lib/fastruby/reductor/modules/recursive.rb +31 -0
- data/lib/fastruby/reductor/reductor.rb +39 -0
- data/lib/fastruby/set_tree.rb +7 -1
- data/lib/fastruby/sexp_extension.rb +6 -0
- data/lib/fastruby/translator/modules/block.rb +4 -4
- data/lib/fastruby/translator/modules/call.rb +9 -26
- data/lib/fastruby/translator/modules/defn.rb +5 -3
- data/lib/fastruby/translator/modules/directive.rb +42 -0
- data/lib/fastruby/translator/modules/exceptions.rb +12 -30
- data/lib/fastruby/translator/modules/flow.rb +33 -83
- data/lib/fastruby/translator/modules/iter.rb +4 -7
- data/lib/fastruby/translator/modules/literal.rb +11 -25
- data/lib/fastruby/translator/modules/logical.rb +5 -3
- data/lib/fastruby/translator/modules/method_group.rb +4 -3
- data/lib/fastruby/translator/modules/nonlocal.rb +7 -5
- data/lib/fastruby/translator/modules/static.rb +242 -0
- data/lib/fastruby/translator/modules/variable.rb +16 -9
- data/lib/fastruby/translator/scope_mode_helper.rb +2 -27
- data/lib/fastruby/translator/translator.rb +131 -60
- data/lib/fastruby/translator/translator_modules.rb +6 -2
- data/lib/fastruby.rb +1 -1
- data/spec/reductor/base_spec.rb +46 -0
- data/spec/ruby/base_spec.rb~ +394 -0
- data/spec/ruby/block/arguments_spec.rb~ +214 -0
- data/spec/ruby/block/proc_as_block_spec.rb~ +23 -0
- data/spec/ruby/block/retry_spec.rb~ +43 -0
- data/spec/ruby/block_spec.rb~ +520 -0
- data/spec/ruby/defn/replacement_spec.rb~ +102 -0
- data/spec/ruby/integrity_spec.rb~ +40 -0
- data/spec/ruby/singleton_spec.rb~ +76 -0
- data/spec/scope_mode/base_spec.rb +14 -5
- data/spec/scope_mode/block_spec.rb +18 -9
- data/spec/scope_mode/call_spec.rb +11 -2
- data/spec/scope_mode/exception_spec.rb +11 -2
- data/spec/scope_mode/flow_spec.rb +18 -8
- data/spec/scope_mode/optimization_spec.rb +21 -13
- data/spec/static/base_spec.rb +54 -0
- data/spec/static/flow_spec.rb +48 -0
- data/spec/static/operator_spec.rb +104 -0
- metadata +58 -8
@@ -0,0 +1,242 @@
|
|
1
|
+
=begin
|
2
|
+
|
3
|
+
This file is part of the fastruby project, http://github.com/tario/fastruby
|
4
|
+
|
5
|
+
Copyright (c) 2011 Roberto Dario Seminara <robertodarioseminara@gmail.com>
|
6
|
+
|
7
|
+
fastruby is free software: you can redistribute it and/or modify
|
8
|
+
it under the terms of the gnu general public license as published by
|
9
|
+
the free software foundation, either version 3 of the license, or
|
10
|
+
(at your option) any later version.
|
11
|
+
|
12
|
+
fastruby is distributed in the hope that it will be useful,
|
13
|
+
but without any warranty; without even the implied warranty of
|
14
|
+
merchantability or fitness for a particular purpose. see the
|
15
|
+
gnu general public license for more details.
|
16
|
+
|
17
|
+
you should have received a copy of the gnu general public license
|
18
|
+
along with fastruby. if not, see <http://www.gnu.org/licenses/>.
|
19
|
+
|
20
|
+
=end
|
21
|
+
module FastRuby
|
22
|
+
class Context
|
23
|
+
define_translator_for(:iter, :arity => 1, :priority => 1) { |*x|
|
24
|
+
ret = nil
|
25
|
+
tree = x.first
|
26
|
+
|
27
|
+
enable_handler_group(:static_call) do
|
28
|
+
ret = x.size == 1 ? to_c(tree[3]) : to_c(tree[3], x.last)
|
29
|
+
end
|
30
|
+
ret
|
31
|
+
}.condition{ |*x|
|
32
|
+
tree = x.first
|
33
|
+
tree.node_type == :iter && tree[1][2] == :_static
|
34
|
+
}
|
35
|
+
|
36
|
+
define_translator_for(:iter, :arity => 1, :priority => 1) { |*x|
|
37
|
+
ret = nil
|
38
|
+
tree = x.first
|
39
|
+
|
40
|
+
disable_handler_group(:static_call) do
|
41
|
+
ret = x.size == 1 ? to_c(tree[3]) : to_c(tree[3], x.last)
|
42
|
+
end
|
43
|
+
ret
|
44
|
+
}.condition{ |*x|
|
45
|
+
tree = x.first
|
46
|
+
tree.node_type == :iter && tree[1][2] == :_dynamic
|
47
|
+
}
|
48
|
+
|
49
|
+
handler_scope(:group => :static_call, :priority => 1000) do
|
50
|
+
define_translator_for(:call) do |tree, result=nil|
|
51
|
+
method_name = tree[2].to_s
|
52
|
+
recv_tree = tree[1]
|
53
|
+
|
54
|
+
if recv_tree
|
55
|
+
if (not tree[2].to_s =~ /^[a-zA-Z]/) and tree[2].to_s.size <= 3
|
56
|
+
c_op = tree[2].to_s
|
57
|
+
c_op = '==' if tree[2] == :===
|
58
|
+
code = "( ( #{to_c(tree[1])} )#{c_op}(#{to_c(tree[3][1])}) )"
|
59
|
+
else
|
60
|
+
raise "invalid static call #{method_name}"
|
61
|
+
end
|
62
|
+
else
|
63
|
+
args = tree[3][1..-1].map(&method(:to_c)).join(",")
|
64
|
+
code = "#{method_name}( #{args} )"
|
65
|
+
end
|
66
|
+
|
67
|
+
if result
|
68
|
+
"#{result} = #{code};"
|
69
|
+
else
|
70
|
+
code
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
define_translator_for(:lit) do |tree, result=nil|
|
75
|
+
if result
|
76
|
+
"#{result} = #{tree[1]};"
|
77
|
+
else
|
78
|
+
tree[1].to_s
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
define_translator_for(:if) do |tree, result_variable_ = nil|
|
83
|
+
condition_tree = tree[1]
|
84
|
+
impl_tree = tree[2]
|
85
|
+
else_tree = tree[3]
|
86
|
+
|
87
|
+
result_variable = result_variable_ || "last_expression"
|
88
|
+
|
89
|
+
code = "
|
90
|
+
{
|
91
|
+
VALUE condition_result;
|
92
|
+
#{to_c condition_tree, "condition_result"};
|
93
|
+
if (condition_result) {
|
94
|
+
#{to_c impl_tree, result_variable};
|
95
|
+
}#{else_tree ?
|
96
|
+
" else {
|
97
|
+
#{to_c else_tree, result_variable};
|
98
|
+
}
|
99
|
+
" : ""
|
100
|
+
}
|
101
|
+
}
|
102
|
+
"
|
103
|
+
|
104
|
+
if result_variable_
|
105
|
+
code
|
106
|
+
else
|
107
|
+
inline_block code + "; return last_expression;"
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
define_translator_for(:while) do |tree, result_var = nil|
|
112
|
+
begin_while = "begin_while_"+rand(10000000).to_s
|
113
|
+
end_while = "end_while_"+rand(10000000).to_s
|
114
|
+
aux_varname = "_aux_" + rand(10000000).to_s
|
115
|
+
code = "
|
116
|
+
{
|
117
|
+
VALUE while_condition;
|
118
|
+
VALUE #{aux_varname};
|
119
|
+
|
120
|
+
#{begin_while}:
|
121
|
+
#{to_c tree[1], "while_condition"};
|
122
|
+
if (!(while_condition)) goto #{end_while};
|
123
|
+
#{to_c tree[2], aux_varname};
|
124
|
+
goto #{begin_while};
|
125
|
+
#{end_while}:
|
126
|
+
|
127
|
+
#{
|
128
|
+
if result_var
|
129
|
+
"#{result_var} = Qnil;"
|
130
|
+
else
|
131
|
+
"return Qnil;"
|
132
|
+
end
|
133
|
+
}
|
134
|
+
}
|
135
|
+
"
|
136
|
+
|
137
|
+
if result_var
|
138
|
+
code
|
139
|
+
else
|
140
|
+
inline_block code
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
define_translator_for(:and) do |tree, return_var = nil|
|
146
|
+
if return_var
|
147
|
+
"
|
148
|
+
{
|
149
|
+
VALUE op1 = Qnil;
|
150
|
+
VALUE op2 = Qnil;
|
151
|
+
#{to_c tree[1], "op1"};
|
152
|
+
#{to_c tree[2], "op2"};
|
153
|
+
#{return_var} = ((op1) &&(op2));
|
154
|
+
}
|
155
|
+
"
|
156
|
+
else
|
157
|
+
"((#{to_c tree[1]}) && (#{to_c tree[2]}))"
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|
161
|
+
|
162
|
+
define_translator_for(:or) do |tree, return_var = nil|
|
163
|
+
if return_var
|
164
|
+
"
|
165
|
+
{
|
166
|
+
VALUE op1 = Qnil;
|
167
|
+
VALUE op2 = Qnil;
|
168
|
+
#{to_c tree[1], "op1"};
|
169
|
+
#{to_c tree[2], "op2"};
|
170
|
+
#{return_var} = ((op1) ||(op2));
|
171
|
+
}
|
172
|
+
"
|
173
|
+
else
|
174
|
+
"((#{to_c tree[1]}) || (#{to_c tree[2]}))"
|
175
|
+
end
|
176
|
+
|
177
|
+
end
|
178
|
+
|
179
|
+
define_translator_for(:not) do |tree, return_var = nil|
|
180
|
+
if return_var
|
181
|
+
"
|
182
|
+
{
|
183
|
+
VALUE op1 = Qnil;
|
184
|
+
#{to_c tree[1], "op1"};
|
185
|
+
#{return_var} = ((op1) ? 0: 1);
|
186
|
+
}
|
187
|
+
"
|
188
|
+
else
|
189
|
+
"((#{to_c tree[1]}) ? 0 : 1)"
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
end
|
194
|
+
|
195
|
+
define_method_handler(:initialize_to_c){|*x|}.condition do |*x|
|
196
|
+
disable_handler_group(:static_call, :to_c); false
|
197
|
+
end
|
198
|
+
|
199
|
+
|
200
|
+
define_method_handler(:infer_value) { |tree|
|
201
|
+
Value.new(eval(tree[1].to_s))
|
202
|
+
}.condition{|tree| tree.node_type == :const}
|
203
|
+
|
204
|
+
define_method_handler(:infer_value) { |tree|
|
205
|
+
args_tree = tree[3]
|
206
|
+
receiver_tree = tree[1]
|
207
|
+
|
208
|
+
value_1 = infer_value(receiver_tree)
|
209
|
+
value_2 = infer_value(args_tree[1])
|
210
|
+
|
211
|
+
next false unless (value_1 and value_2)
|
212
|
+
|
213
|
+
Value.new(value_1.value == value_2.value)
|
214
|
+
}.condition{|tree|
|
215
|
+
next false unless tree.node_type == :call
|
216
|
+
|
217
|
+
args_tree = tree[3]
|
218
|
+
method_name = tree[2]
|
219
|
+
|
220
|
+
next false unless method_name == :==
|
221
|
+
next false if args_tree.size < 2
|
222
|
+
|
223
|
+
true
|
224
|
+
}
|
225
|
+
define_method_handler(:infer_value) { |tree|
|
226
|
+
args_tree = tree[3]
|
227
|
+
receiver_tree = tree[1]
|
228
|
+
infered_type = infer_type(receiver_tree)
|
229
|
+
|
230
|
+
if infered_type
|
231
|
+
Value.new(infered_type)
|
232
|
+
else
|
233
|
+
nil
|
234
|
+
end
|
235
|
+
}.condition{|tree|
|
236
|
+
next false unless tree.node_type == :call
|
237
|
+
method_name = tree[2]
|
238
|
+
next false unless method_name == :_class
|
239
|
+
true
|
240
|
+
}
|
241
|
+
end
|
242
|
+
end
|
@@ -19,14 +19,13 @@ along with fastruby. if not, see <http://www.gnu.org/licenses/>.
|
|
19
19
|
|
20
20
|
=end
|
21
21
|
module FastRuby
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
class Context
|
23
|
+
define_translator_for(:cvar, :method => :to_c_cvar, :arity => 1)
|
26
24
|
def to_c_cvar(tree)
|
27
25
|
"rb_cvar_get(CLASS_OF(plocals->self) != rb_cClass ? CLASS_OF(plocals->self) : plocals->self,#{intern_num tree[1]})"
|
28
26
|
end
|
29
27
|
|
28
|
+
define_translator_for(:cvasgn, :method => :to_c_cvasgn)
|
30
29
|
def to_c_cvasgn(tree, result_var = nil)
|
31
30
|
if result_var
|
32
31
|
"
|
@@ -50,6 +49,7 @@ module FastRuby
|
|
50
49
|
end
|
51
50
|
end
|
52
51
|
|
52
|
+
define_translator_for(:gvar, :method => :to_c_gvar, :arity => 1)
|
53
53
|
def to_c_gvar(tree)
|
54
54
|
if (tree[1] == :$!)
|
55
55
|
"pframe->thread_data->exception"
|
@@ -58,6 +58,7 @@ module FastRuby
|
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
61
|
+
define_translator_for(:gasgn, :method => :to_c_gasgn)
|
61
62
|
def to_c_gasgn(tree, result_var = nil)
|
62
63
|
if result_var
|
63
64
|
"
|
@@ -71,10 +72,12 @@ module FastRuby
|
|
71
72
|
end
|
72
73
|
end
|
73
74
|
|
75
|
+
define_translator_for(:ivar, :method => :to_c_ivar, :arity => 1)
|
74
76
|
def to_c_ivar(tree)
|
75
77
|
"rb_ivar_get(#{locals_accessor}self,#{intern_num tree[1]})"
|
76
78
|
end
|
77
79
|
|
80
|
+
define_translator_for(:iasgn, :method => :to_c_iasgn)
|
78
81
|
def to_c_iasgn(tree, result_var = nil)
|
79
82
|
if result_var
|
80
83
|
"
|
@@ -88,10 +91,11 @@ module FastRuby
|
|
88
91
|
end
|
89
92
|
end
|
90
93
|
|
91
|
-
|
94
|
+
define_translator_for(:const, :arity => 1) do |tree|
|
92
95
|
"rb_const_get(CLASS_OF(plocals->self), #{intern_num(tree[1])})"
|
93
96
|
end
|
94
97
|
|
98
|
+
define_translator_for(:cdecl, :method => :to_c_cdecl)
|
95
99
|
def to_c_cdecl(tree, result_var_ = nil)
|
96
100
|
|
97
101
|
result_var = result_var_ || "value"
|
@@ -136,10 +140,12 @@ module FastRuby
|
|
136
140
|
end
|
137
141
|
end
|
138
142
|
|
143
|
+
define_translator_for(:colon3, :method => :to_c_colon3, :arity => 1)
|
139
144
|
def to_c_colon3(tree)
|
140
145
|
"rb_const_get_from(rb_cObject, #{intern_num tree[1]})"
|
141
146
|
end
|
142
|
-
|
147
|
+
|
148
|
+
define_translator_for(:colon2, :method => :to_c_colon2)
|
143
149
|
def to_c_colon2(tree, result_var = nil)
|
144
150
|
code = "
|
145
151
|
{
|
@@ -194,6 +200,7 @@ module FastRuby
|
|
194
200
|
end
|
195
201
|
end
|
196
202
|
|
203
|
+
define_translator_for(:lasgn, :method => :to_c_lasgn)
|
197
204
|
def to_c_lasgn(tree, result_var = nil)
|
198
205
|
code = "
|
199
206
|
{
|
@@ -244,12 +251,12 @@ module FastRuby
|
|
244
251
|
end
|
245
252
|
end
|
246
253
|
end
|
247
|
-
|
248
|
-
|
254
|
+
|
255
|
+
define_translator_for(:lvar, :arity => 1) do |tree|
|
249
256
|
locals_accessor + tree[1].to_s
|
250
257
|
end
|
251
258
|
|
252
|
-
|
259
|
+
define_translator_for(:defined, :method => :to_c_defined, :arity => 1)
|
253
260
|
def to_c_defined(tree)
|
254
261
|
nt = tree[1].node_type
|
255
262
|
|
@@ -26,34 +26,8 @@ module FastRuby
|
|
26
26
|
new.get_scope_mode(tree_)
|
27
27
|
end
|
28
28
|
|
29
|
-
def when_array_to_if(array)
|
30
|
-
if array.size == 1
|
31
|
-
array[0] || s(:nil)
|
32
|
-
else
|
33
|
-
first_when_tree = array[0]
|
34
|
-
comparers = first_when_tree[1][1..-1]
|
35
|
-
|
36
|
-
condition_tree = s(:or)
|
37
|
-
comparers.each do |st|
|
38
|
-
condition_tree << s(:call, st, :===, s(:arglist, s(:lvar, :temporal_case_var)))
|
39
|
-
end
|
40
|
-
|
41
|
-
s(:if, condition_tree, first_when_tree[2], when_array_to_if(array[1..-1]) )
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
29
|
def get_scope_mode(tree_)
|
46
|
-
tree = FastRuby::FastRubySexp.from_sexp(tree_)
|
47
|
-
if subtree.node_type == :for
|
48
|
-
s(:iter,s(:call, subtree[1],:each, s(:arglist)),subtree[2], subtree[3] )
|
49
|
-
elsif subtree.node_type == :case
|
50
|
-
ifs = when_array_to_if(subtree[2..-1])
|
51
|
-
|
52
|
-
s(:block, s(:lasgn, :temporal_case_var, subtree[1]), ifs)
|
53
|
-
else
|
54
|
-
nil
|
55
|
-
end
|
56
|
-
end
|
30
|
+
tree = FastRuby::FastRubySexp.from_sexp(tree_)
|
57
31
|
|
58
32
|
if tree.node_type == :defn
|
59
33
|
args_tree = tree[2]
|
@@ -95,6 +69,7 @@ module FastRuby
|
|
95
69
|
writes = Set.new
|
96
70
|
|
97
71
|
path.each do |st2|
|
72
|
+
next unless st2
|
98
73
|
if st2.node_type == :call
|
99
74
|
if has_call and st2[1] == nil
|
100
75
|
return :dag
|