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.
Files changed (78) hide show
  1. data/CHANGELOG +17 -1
  2. data/Rakefile +1 -1
  3. data/ext/fastruby_base/fastruby_base.inl +81 -3
  4. data/lib/fastruby/fastruby_sexp.rb +21 -0
  5. data/lib/fastruby/getlocals.rb +2 -1
  6. data/lib/fastruby/object.rb +1 -1
  7. data/lib/fastruby/sexp_extension.rb +189 -0
  8. data/lib/fastruby/sexp_extension_edges.rb +210 -0
  9. data/lib/fastruby/translator/modules/block.rb +29 -22
  10. data/lib/fastruby/translator/modules/call.rb +211 -34
  11. data/lib/fastruby/translator/modules/defn.rb +64 -29
  12. data/lib/fastruby/translator/modules/exceptions.rb +1 -1
  13. data/lib/fastruby/translator/modules/flow.rb +93 -31
  14. data/lib/fastruby/translator/modules/iter.rb +277 -340
  15. data/lib/fastruby/translator/modules/literal.rb +97 -20
  16. data/lib/fastruby/translator/modules/logical.rb +40 -5
  17. data/lib/fastruby/translator/modules/method_group.rb +41 -19
  18. data/lib/fastruby/translator/modules/nonlocal.rb +74 -29
  19. data/lib/fastruby/translator/modules/variable.rb +151 -42
  20. data/lib/fastruby/translator/scope_mode_helper.rb +161 -0
  21. data/lib/fastruby/translator/translator.rb +389 -302
  22. data/lib/fastruby.rb +1 -1
  23. data/lib/fastruby.rb~ +36 -0
  24. data/spec/edges_helper.rb +91 -0
  25. data/spec/graph/base_spec.rb +35 -0
  26. data/spec/graph/path_spec.rb +48 -0
  27. data/spec/graph/vertex_spec.rb +58 -0
  28. data/spec/ruby/block/proc_as_block_spec.rb +214 -0
  29. data/spec/ruby/block/redo_spec.rb +133 -0
  30. data/spec/ruby/defn/single_function_spec.rb +50 -0
  31. data/spec/scope_mode/base_spec.rb +55 -0
  32. data/spec/scope_mode/block_spec.rb +105 -0
  33. data/spec/scope_mode/call_spec.rb +24 -0
  34. data/spec/scope_mode/exception_spec.rb +34 -0
  35. data/spec/scope_mode/flow_spec.rb +99 -0
  36. data/spec/scope_mode/optimization_spec.rb +130 -0
  37. data/spec/sexp2graph/base_spec.rb +36 -0
  38. data/spec/sexp2graph/exception_spec.rb +172 -0
  39. data/spec/sexp2graph/flow_spec.rb +67 -0
  40. data/spec/sexp2graph/logical_spec.rb +21 -0
  41. data/spec/sexp2graph/variable_spec.rb +26 -0
  42. metadata +110 -120
  43. data/lib/fastruby/self +0 -82
  44. data/lib/len +0 -280
  45. data/spec/block/proc_as_block_spec.rb +0 -111
  46. data/spec/block/redo_spec.rb +0 -67
  47. /data/spec/{base_spec.rb → ruby/base_spec.rb} +0 -0
  48. /data/spec/{block → ruby/block}/arguments_spec.rb +0 -0
  49. /data/spec/{block → ruby/block}/block_as_proc_spec.rb +0 -0
  50. /data/spec/{block → ruby/block}/break_spec.rb +0 -0
  51. /data/spec/{block → ruby/block}/callcc_spec.rb +0 -0
  52. /data/spec/{block → ruby/block}/lambda_spec.rb +0 -0
  53. /data/spec/{block → ruby/block}/next_spec.rb +0 -0
  54. /data/spec/{block → ruby/block}/proc_spec.rb +0 -0
  55. /data/spec/{block → ruby/block}/retry_spec.rb +0 -0
  56. /data/spec/{block_spec.rb → ruby/block_spec.rb} +0 -0
  57. /data/spec/{call → ruby/call}/base_call_spec.rb +0 -0
  58. /data/spec/{call → ruby/call}/multiple_args_spec.rb +0 -0
  59. /data/spec/{control_spec.rb → ruby/control_spec.rb} +0 -0
  60. /data/spec/{defn → ruby/defn}/default_args_spec.rb +0 -0
  61. /data/spec/{defn → ruby/defn}/multiple_args_spec.rb +0 -0
  62. /data/spec/{defn → ruby/defn}/replacement_spec.rb +0 -0
  63. /data/spec/{exception → ruby/exception}/base_spec.rb +0 -0
  64. /data/spec/{exception → ruby/exception}/ensure_spec.rb +0 -0
  65. /data/spec/{exception → ruby/exception}/exc_trap_spec.rb +0 -0
  66. /data/spec/{exception → ruby/exception}/internal_ex_spec.rb +0 -0
  67. /data/spec/{exception → ruby/exception}/syntaxis_spec.rb +0 -0
  68. /data/spec/{expression_spec.rb → ruby/expression_spec.rb} +0 -0
  69. /data/spec/{flow_control → ruby/flow_control}/case_spec.rb +0 -0
  70. /data/spec/{flow_control → ruby/flow_control}/for_spec.rb +0 -0
  71. /data/spec/{integrity_spec.rb → ruby/integrity_spec.rb} +0 -0
  72. /data/spec/{jump → ruby/jump}/next_spec.rb +0 -0
  73. /data/spec/{literal_spec.rb → ruby/literal_spec.rb} +0 -0
  74. /data/spec/{module_spec.rb → ruby/module_spec.rb} +0 -0
  75. /data/spec/{return_spec.rb → ruby/return_spec.rb} +0 -0
  76. /data/spec/{singleton_spec.rb → ruby/singleton_spec.rb} +0 -0
  77. /data/spec/{sugar_spec.rb → ruby/sugar_spec.rb} +0 -0
  78. /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
- "_rb_ivar_set(#{locals_accessor}self,#{intern_num tree[1]},#{to_c tree[2]})"
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
- inline_block "
61
- // set constant #{tree[1].to_s}
62
- VALUE val = #{to_c tree[2]};
63
- rb_const_set(rb_cObject, #{intern_num tree[1]}, val);
64
- return val;
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
- inline_block "
70
- // set constant #{tree[1].to_s}
71
- VALUE val = #{to_c tree[2]};
72
- VALUE klass = #{to_c tree[1][1]};
73
- rb_const_set(klass, #{intern_num tree[1][2]}, val);
74
- return val;
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
- inline_block "
120
+ code = "
121
+ {
78
122
  // set constant #{tree[1].to_s}
79
- VALUE val = #{to_c tree[2]};
80
- rb_const_set(rb_cObject, #{intern_num tree[1][1]}, val);
81
- return val;
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
- inline_block "
93
- VALUE klass = #{to_c tree[1]};
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
- return rb_const_get_from(klass, #{intern_num tree[2]});
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
- return rb_funcall(klass, #{intern_num tree[2]}, 0, 0);
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
- return Qnil;
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
- if options[:validate_lvar_types]
116
- klass = @infer_lvar_map[tree[1]]
117
- if klass
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
- verify_type_function = proc { |name| "
120
- static VALUE #{name}(VALUE arg, void* pframe ) {
121
- if (CLASS_OF(arg)!=#{literal_value klass}) {
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
- return arg;
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
- "_lvar_assing(&#{locals_accessor}#{tree[1]},#{to_c tree[2]})"
222
+ code
133
223
  end
134
224
  else
135
- "_lvar_assing(&#{locals_accessor}#{tree[1]},#{to_c tree[2]})"
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