fastruby 0.0.16 → 0.0.17
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 +17 -1
- data/Rakefile +1 -1
- data/ext/fastruby_base/fastruby_base.inl +81 -3
- data/lib/fastruby/fastruby_sexp.rb +21 -0
- data/lib/fastruby/getlocals.rb +2 -1
- data/lib/fastruby/object.rb +1 -1
- data/lib/fastruby/sexp_extension.rb +189 -0
- data/lib/fastruby/sexp_extension_edges.rb +210 -0
- data/lib/fastruby/translator/modules/block.rb +29 -22
- data/lib/fastruby/translator/modules/call.rb +211 -34
- data/lib/fastruby/translator/modules/defn.rb +64 -29
- data/lib/fastruby/translator/modules/exceptions.rb +1 -1
- data/lib/fastruby/translator/modules/flow.rb +93 -31
- data/lib/fastruby/translator/modules/iter.rb +277 -340
- data/lib/fastruby/translator/modules/literal.rb +97 -20
- data/lib/fastruby/translator/modules/logical.rb +40 -5
- data/lib/fastruby/translator/modules/method_group.rb +41 -19
- data/lib/fastruby/translator/modules/nonlocal.rb +74 -29
- data/lib/fastruby/translator/modules/variable.rb +151 -42
- data/lib/fastruby/translator/scope_mode_helper.rb +161 -0
- data/lib/fastruby/translator/translator.rb +389 -302
- data/lib/fastruby.rb +1 -1
- data/lib/fastruby.rb~ +36 -0
- data/spec/edges_helper.rb +91 -0
- data/spec/graph/base_spec.rb +35 -0
- data/spec/graph/path_spec.rb +48 -0
- data/spec/graph/vertex_spec.rb +58 -0
- data/spec/ruby/block/proc_as_block_spec.rb +214 -0
- data/spec/ruby/block/redo_spec.rb +133 -0
- data/spec/ruby/defn/single_function_spec.rb +50 -0
- data/spec/scope_mode/base_spec.rb +55 -0
- data/spec/scope_mode/block_spec.rb +105 -0
- data/spec/scope_mode/call_spec.rb +24 -0
- data/spec/scope_mode/exception_spec.rb +34 -0
- data/spec/scope_mode/flow_spec.rb +99 -0
- data/spec/scope_mode/optimization_spec.rb +130 -0
- data/spec/sexp2graph/base_spec.rb +36 -0
- data/spec/sexp2graph/exception_spec.rb +172 -0
- data/spec/sexp2graph/flow_spec.rb +67 -0
- data/spec/sexp2graph/logical_spec.rb +21 -0
- data/spec/sexp2graph/variable_spec.rb +26 -0
- metadata +110 -120
- data/lib/fastruby/self +0 -82
- data/lib/len +0 -280
- data/spec/block/proc_as_block_spec.rb +0 -111
- data/spec/block/redo_spec.rb +0 -67
- /data/spec/{base_spec.rb → ruby/base_spec.rb} +0 -0
- /data/spec/{block → ruby/block}/arguments_spec.rb +0 -0
- /data/spec/{block → ruby/block}/block_as_proc_spec.rb +0 -0
- /data/spec/{block → ruby/block}/break_spec.rb +0 -0
- /data/spec/{block → ruby/block}/callcc_spec.rb +0 -0
- /data/spec/{block → ruby/block}/lambda_spec.rb +0 -0
- /data/spec/{block → ruby/block}/next_spec.rb +0 -0
- /data/spec/{block → ruby/block}/proc_spec.rb +0 -0
- /data/spec/{block → ruby/block}/retry_spec.rb +0 -0
- /data/spec/{block_spec.rb → ruby/block_spec.rb} +0 -0
- /data/spec/{call → ruby/call}/base_call_spec.rb +0 -0
- /data/spec/{call → ruby/call}/multiple_args_spec.rb +0 -0
- /data/spec/{control_spec.rb → ruby/control_spec.rb} +0 -0
- /data/spec/{defn → ruby/defn}/default_args_spec.rb +0 -0
- /data/spec/{defn → ruby/defn}/multiple_args_spec.rb +0 -0
- /data/spec/{defn → ruby/defn}/replacement_spec.rb +0 -0
- /data/spec/{exception → ruby/exception}/base_spec.rb +0 -0
- /data/spec/{exception → ruby/exception}/ensure_spec.rb +0 -0
- /data/spec/{exception → ruby/exception}/exc_trap_spec.rb +0 -0
- /data/spec/{exception → ruby/exception}/internal_ex_spec.rb +0 -0
- /data/spec/{exception → ruby/exception}/syntaxis_spec.rb +0 -0
- /data/spec/{expression_spec.rb → ruby/expression_spec.rb} +0 -0
- /data/spec/{flow_control → ruby/flow_control}/case_spec.rb +0 -0
- /data/spec/{flow_control → ruby/flow_control}/for_spec.rb +0 -0
- /data/spec/{integrity_spec.rb → ruby/integrity_spec.rb} +0 -0
- /data/spec/{jump → ruby/jump}/next_spec.rb +0 -0
- /data/spec/{literal_spec.rb → ruby/literal_spec.rb} +0 -0
- /data/spec/{module_spec.rb → ruby/module_spec.rb} +0 -0
- /data/spec/{return_spec.rb → ruby/return_spec.rb} +0 -0
- /data/spec/{singleton_spec.rb → ruby/singleton_spec.rb} +0 -0
- /data/spec/{sugar_spec.rb → ruby/sugar_spec.rb} +0 -0
- /data/spec/{variable_spec.rb → ruby/variable_spec.rb} +0 -0
@@ -27,8 +27,27 @@ module FastRuby
|
|
27
27
|
"rb_cvar_get(CLASS_OF(plocals->self) != rb_cClass ? CLASS_OF(plocals->self) : plocals->self,#{intern_num tree[1]})"
|
28
28
|
end
|
29
29
|
|
30
|
-
def to_c_cvasgn(tree)
|
30
|
+
def to_c_cvasgn(tree, result_var = nil)
|
31
|
+
if result_var
|
32
|
+
"
|
33
|
+
{
|
34
|
+
VALUE recv = CLASS_OF(plocals->self) != rb_cClass ? CLASS_OF(plocals->self) : plocals->self;
|
35
|
+
|
36
|
+
#{to_c tree[2], result_var};
|
37
|
+
|
38
|
+
#{if RUBY_VERSION =~ /^1\.9/
|
39
|
+
"rb_cvar_set(recv,#{intern_num tree[1]},#{result_var});"
|
40
|
+
elsif RUBY_VERSION =~ /^1\.8/
|
41
|
+
"rb_cvar_set(recv,#{intern_num tree[1]},#{result_var},Qfalse);"
|
42
|
+
else
|
43
|
+
raise RuntimeError, "unsupported ruby version #{RUBY_VERSION}"
|
44
|
+
end
|
45
|
+
}
|
46
|
+
}
|
47
|
+
"
|
48
|
+
else
|
31
49
|
"__rb_cvar_set(CLASS_OF(plocals->self) != rb_cClass ? CLASS_OF(plocals->self) : plocals->self,#{intern_num tree[1]},#{to_c tree[2]},Qfalse)"
|
50
|
+
end
|
32
51
|
end
|
33
52
|
|
34
53
|
def to_c_gvar(tree)
|
@@ -39,48 +58,81 @@ module FastRuby
|
|
39
58
|
end
|
40
59
|
end
|
41
60
|
|
42
|
-
def to_c_gasgn(tree)
|
61
|
+
def to_c_gasgn(tree, result_var = nil)
|
62
|
+
if result_var
|
63
|
+
"
|
64
|
+
{
|
65
|
+
#{to_c tree[2], result_var};
|
66
|
+
rb_gvar_set((void*)#{global_entry(tree[1])},#{result_var});
|
67
|
+
}
|
68
|
+
"
|
69
|
+
else
|
43
70
|
"_rb_gvar_set((void*)#{global_entry(tree[1])}, #{to_c tree[2]})"
|
71
|
+
end
|
44
72
|
end
|
45
73
|
|
46
74
|
def to_c_ivar(tree)
|
47
75
|
"rb_ivar_get(#{locals_accessor}self,#{intern_num tree[1]})"
|
48
76
|
end
|
49
77
|
|
50
|
-
def to_c_iasgn(tree)
|
51
|
-
|
78
|
+
def to_c_iasgn(tree, result_var = nil)
|
79
|
+
if result_var
|
80
|
+
"
|
81
|
+
{
|
82
|
+
#{to_c tree[2], result_var};
|
83
|
+
rb_ivar_set(#{locals_accessor}self,#{intern_num tree[1]},#{result_var});
|
84
|
+
}
|
85
|
+
"
|
86
|
+
else
|
87
|
+
"_rb_ivar_set(#{locals_accessor}self,#{intern_num tree[1]},#{to_c tree[2]})"
|
88
|
+
end
|
52
89
|
end
|
53
90
|
|
54
91
|
def to_c_const(tree)
|
55
92
|
"rb_const_get(CLASS_OF(plocals->self), #{intern_num(tree[1])})"
|
56
93
|
end
|
57
94
|
|
58
|
-
def to_c_cdecl(tree)
|
95
|
+
def to_c_cdecl(tree, result_var_ = nil)
|
96
|
+
|
97
|
+
result_var = result_var_ || "value"
|
98
|
+
|
59
99
|
if tree[1].instance_of? Symbol
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
100
|
+
code = "
|
101
|
+
{
|
102
|
+
// set constant #{tree[1].to_s}
|
103
|
+
#{to_c tree[2], result_var};
|
104
|
+
rb_const_set(rb_cObject, #{intern_num tree[1]}, #{result_var});
|
105
|
+
}
|
65
106
|
"
|
66
107
|
elsif tree[1].instance_of? FastRuby::FastRubySexp
|
67
108
|
|
68
109
|
if tree[1].node_type == :colon2
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
110
|
+
code = "
|
111
|
+
{
|
112
|
+
// set constant #{tree[1].to_s}
|
113
|
+
#{to_c tree[2], result_var};
|
114
|
+
VALUE klass = Qnil;
|
115
|
+
#{to_c tree[1][1], "klass"};
|
116
|
+
rb_const_set(klass, #{intern_num tree[1][2]}, #{result_var});
|
117
|
+
}
|
75
118
|
"
|
76
119
|
elsif tree[1].node_type == :colon3
|
77
|
-
|
120
|
+
code = "
|
121
|
+
{
|
78
122
|
// set constant #{tree[1].to_s}
|
79
|
-
|
80
|
-
rb_const_set(rb_cObject, #{intern_num tree[1][1]},
|
81
|
-
|
123
|
+
#{to_c tree[2], result_var};
|
124
|
+
rb_const_set(rb_cObject, #{intern_num tree[1][1]}, #{result_var});
|
125
|
+
}
|
82
126
|
"
|
83
127
|
end
|
128
|
+
|
129
|
+
if result_var_
|
130
|
+
code
|
131
|
+
else
|
132
|
+
inline_block "VALUE #{result_var} = Qnil;\n" + code + "
|
133
|
+
return #{result_var};
|
134
|
+
"
|
135
|
+
end
|
84
136
|
end
|
85
137
|
end
|
86
138
|
|
@@ -88,15 +140,29 @@ module FastRuby
|
|
88
140
|
"rb_const_get_from(rb_cObject, #{intern_num tree[1]})"
|
89
141
|
end
|
90
142
|
|
91
|
-
def to_c_colon2(tree)
|
92
|
-
|
93
|
-
|
143
|
+
def to_c_colon2(tree, result_var = nil)
|
144
|
+
code = "
|
145
|
+
{
|
146
|
+
VALUE klass = Qnil;
|
147
|
+
|
148
|
+
#{to_c tree[1],"klass"};
|
149
|
+
#{
|
150
|
+
if result_var
|
151
|
+
"#{result_var} = Qnil;"
|
152
|
+
end
|
153
|
+
}
|
94
154
|
|
95
155
|
if (rb_is_const_id(#{intern_num tree[2]})) {
|
96
156
|
switch (TYPE(klass)) {
|
97
157
|
case T_CLASS:
|
98
158
|
case T_MODULE:
|
99
|
-
|
159
|
+
#{
|
160
|
+
if result_var
|
161
|
+
"#{result_var} = rb_const_get_from(klass, #{intern_num tree[2]});"
|
162
|
+
else
|
163
|
+
"return rb_const_get_from(klass, #{intern_num tree[2]});"
|
164
|
+
end
|
165
|
+
}
|
100
166
|
break;
|
101
167
|
default:
|
102
168
|
#{_raise("rb_eTypeError","not a class/module")};
|
@@ -104,35 +170,78 @@ module FastRuby
|
|
104
170
|
}
|
105
171
|
}
|
106
172
|
else {
|
107
|
-
|
173
|
+
#{
|
174
|
+
if result_var
|
175
|
+
"#{result_var} = rb_funcall(klass, #{intern_num tree[2]}, 0, 0);"
|
176
|
+
else
|
177
|
+
"return rb_funcall(klass, #{intern_num tree[2]}, 0, 0);"
|
178
|
+
end
|
179
|
+
}
|
108
180
|
}
|
109
|
-
|
110
|
-
|
181
|
+
|
182
|
+
#{
|
183
|
+
unless result_var
|
184
|
+
"return Qnil;"
|
185
|
+
end
|
186
|
+
}
|
187
|
+
}
|
111
188
|
"
|
189
|
+
|
190
|
+
if result_var
|
191
|
+
code
|
192
|
+
else
|
193
|
+
inline_block code
|
194
|
+
end
|
112
195
|
end
|
113
196
|
|
114
|
-
def to_c_lasgn(tree)
|
115
|
-
|
116
|
-
|
117
|
-
|
197
|
+
def to_c_lasgn(tree, result_var = nil)
|
198
|
+
code = "
|
199
|
+
{
|
200
|
+
#{to_c tree[2], result_var};
|
201
|
+
#{locals_accessor}#{tree[1]} = #{result_var};
|
202
|
+
}
|
203
|
+
"
|
118
204
|
|
119
|
-
|
120
|
-
|
121
|
-
|
205
|
+
if result_var
|
206
|
+
if options[:validate_lvar_types]
|
207
|
+
klass = @infer_lvar_map[tree[1]]
|
208
|
+
if klass
|
209
|
+
"
|
210
|
+
{
|
211
|
+
#{to_c tree[2], result_var};
|
212
|
+
if (CLASS_OF(#{result_var})!=#{literal_value klass}) {
|
122
213
|
#{_raise(literal_value(FastRuby::TypeMismatchAssignmentException), "Illegal assignment at runtime (type mismatch)")};
|
123
214
|
}
|
124
|
-
|
215
|
+
#{locals_accessor}#{tree[1]} = #{result_var};
|
125
216
|
}
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
"_lvar_assing(&#{locals_accessor}#{tree[1]}, #{anonymous_function(&verify_type_function)}(#{to_c tree[2]},pframe))"
|
217
|
+
"
|
218
|
+
else
|
219
|
+
code
|
220
|
+
end
|
131
221
|
else
|
132
|
-
|
222
|
+
code
|
133
223
|
end
|
134
224
|
else
|
135
|
-
|
225
|
+
if options[:validate_lvar_types]
|
226
|
+
klass = @infer_lvar_map[tree[1]]
|
227
|
+
if klass
|
228
|
+
verify_type_function = proc { |name| "
|
229
|
+
static VALUE #{name}(VALUE arg, void* pframe ) {
|
230
|
+
if (CLASS_OF(arg)!=#{literal_value klass}) {
|
231
|
+
#{_raise(literal_value(FastRuby::TypeMismatchAssignmentException), "Illegal assignment at runtime (type mismatch)")};
|
232
|
+
}
|
233
|
+
return arg;
|
234
|
+
}
|
235
|
+
"
|
236
|
+
}
|
237
|
+
|
238
|
+
"_lvar_assing(&#{locals_accessor}#{tree[1]}, #{anonymous_function(&verify_type_function)}(#{to_c tree[2]},pframe))"
|
239
|
+
else
|
240
|
+
"_lvar_assing(&#{locals_accessor}#{tree[1]},#{to_c tree[2]})"
|
241
|
+
end
|
242
|
+
else
|
243
|
+
"_lvar_assing(&#{locals_accessor}#{tree[1]},#{to_c tree[2]})"
|
244
|
+
end
|
136
245
|
end
|
137
246
|
end
|
138
247
|
|
@@ -0,0 +1,161 @@
|
|
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
|
+
require "fastruby/sexp_extension"
|
22
|
+
|
23
|
+
module FastRuby
|
24
|
+
class ScopeModeHelper
|
25
|
+
def self.get_scope_mode(tree_)
|
26
|
+
new.get_scope_mode(tree_)
|
27
|
+
end
|
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
|
+
def get_scope_mode(tree_)
|
46
|
+
tree = FastRuby::FastRubySexp.from_sexp(tree_).transform do |subtree|
|
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
|
57
|
+
|
58
|
+
if tree.node_type == :defn
|
59
|
+
args_tree = tree[2]
|
60
|
+
impl_tree = tree[3]
|
61
|
+
elsif tree.node_type == :defs
|
62
|
+
args_tree = tree[3]
|
63
|
+
impl_tree = tree[4]
|
64
|
+
end
|
65
|
+
|
66
|
+
graph = impl_tree.to_graph
|
67
|
+
|
68
|
+
args_tree[1..-1].each do |subtree|
|
69
|
+
return :dag if subtree.to_s =~ /^\&/
|
70
|
+
end
|
71
|
+
|
72
|
+
tree.walk_tree do |subtree|
|
73
|
+
if subtree.node_type == :iter
|
74
|
+
iter_impl = subtree[3]
|
75
|
+
|
76
|
+
return :dag if has_local_variable_access?(subtree[3])
|
77
|
+
return :dag if subtree[2]
|
78
|
+
|
79
|
+
if iter_impl
|
80
|
+
return_node = iter_impl.find_tree{|st2| st2.node_type == :return}
|
81
|
+
|
82
|
+
if return_node
|
83
|
+
return :dag
|
84
|
+
end
|
85
|
+
end
|
86
|
+
elsif subtree.node_type == :block_pass
|
87
|
+
return :dag
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
impl_tree.walk_tree do |subtree|
|
92
|
+
graph.each_path_from(subtree) do |path|
|
93
|
+
# verify path prohibitive for :linear scope (local variable read after call)
|
94
|
+
has_call = false
|
95
|
+
writes = Set.new
|
96
|
+
|
97
|
+
path.each do |st2|
|
98
|
+
if st2.node_type == :call
|
99
|
+
if has_call and st2[1] == nil
|
100
|
+
return :dag
|
101
|
+
end
|
102
|
+
|
103
|
+
writes.clear
|
104
|
+
has_call = true
|
105
|
+
elsif st2.node_type == :iter
|
106
|
+
if has_call and st2[1][1] == nil
|
107
|
+
return :dag
|
108
|
+
end
|
109
|
+
|
110
|
+
writes.clear
|
111
|
+
has_call = true
|
112
|
+
elsif st2.node_type == :lasgn
|
113
|
+
writes << st2[1] # record local writes
|
114
|
+
elsif st2.node_type == :lvar or st2.node_type == :self or
|
115
|
+
st2.node_type == :return or st2.node_type == :yield
|
116
|
+
|
117
|
+
if has_call
|
118
|
+
if st2.node_type == :lvar
|
119
|
+
if writes.include? st2[1]
|
120
|
+
# no problem
|
121
|
+
else
|
122
|
+
# read after call, the scope of this function must be implemented on heap
|
123
|
+
return :dag
|
124
|
+
end
|
125
|
+
else
|
126
|
+
return :dag
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
:linear
|
135
|
+
end
|
136
|
+
|
137
|
+
private
|
138
|
+
def has_local_variable_access?(*trees)
|
139
|
+
trees.each do |tree|
|
140
|
+
return false unless tree.kind_of? FastRuby::FastRubySexp
|
141
|
+
|
142
|
+
tree.walk_tree do |subtree|
|
143
|
+
if subtree.node_type == :lvar or
|
144
|
+
subtree.node_type == :self or
|
145
|
+
subtree.node_type == :yield or
|
146
|
+
subtree.node_type == :return or
|
147
|
+
subtree.node_type == :lasgn
|
148
|
+
return true
|
149
|
+
end
|
150
|
+
|
151
|
+
if subtree.node_type == :call
|
152
|
+
if subtree[1] == nil
|
153
|
+
return true
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
false
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|