fastruby 0.0.18 → 0.0.19

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 (35) hide show
  1. data/CHANGELOG +10 -0
  2. data/Rakefile +2 -1
  3. data/benchmarks/benchmark.rb~ +2 -4
  4. data/benchmarks/benchmark3.rb~ +2 -4
  5. data/ext/fastruby_base/fastruby_base.inl +1 -1
  6. data/lib/fastruby/builder.rb +8 -7
  7. data/lib/fastruby/fastruby_sexp.rb +18 -0
  8. data/lib/fastruby/inliner/modules/call.rb +254 -67
  9. data/lib/fastruby/inliner/modules/recursive.rb +5 -0
  10. data/lib/fastruby/reductor/modules/case.rb +2 -1
  11. data/lib/fastruby/translator/modules/block.rb +65 -59
  12. data/lib/fastruby/translator/modules/call.rb +7 -4
  13. data/lib/fastruby/translator/modules/exceptions.rb +66 -64
  14. data/lib/fastruby/translator/modules/flow.rb +8 -8
  15. data/lib/fastruby/translator/modules/literal.rb +5 -4
  16. data/lib/fastruby/translator/modules/method_group.rb +6 -5
  17. data/lib/fastruby/translator/modules/nonlocal.rb +153 -11
  18. data/lib/fastruby/translator/modules/static.rb +8 -8
  19. data/lib/fastruby/translator/modules/variable.rb +15 -15
  20. data/lib/fastruby/translator/translator.rb +156 -59
  21. data/lib/fastruby.rb +1 -1
  22. data/lib/fastruby.rb~ +36 -0
  23. data/spec/fastruby/inliner/modules/call_spec.rb +0 -0
  24. data/spec/fastruby/translator/modules/nonlocal_spec.rb +0 -0
  25. data/spec/fastruby/translator/translator_spec.rb +0 -0
  26. data/spec/ruby/base_spec.rb~ +5 -5
  27. data/spec/ruby/block/break_spec.rb~ +236 -0
  28. data/spec/ruby/block/lambda_spec.rb~ +38 -0
  29. data/spec/ruby/block/next_spec.rb~ +85 -0
  30. data/spec/ruby/call/base_call_spec.rb~ +83 -0
  31. data/spec/ruby/defn/replacement_spec.rb +52 -2
  32. data/spec/ruby/defn/replacement_spec.rb~ +52 -2
  33. data/spec/ruby/exception/base_spec.rb +22 -1
  34. data/spec/ruby/return_spec.rb~ +99 -0
  35. metadata +30 -10
@@ -42,55 +42,55 @@ module FastRuby
42
42
  }
43
43
 
44
44
  splat_arg = tree.find{|x| x == :yield ? false : x[0] == :splat}
45
- ret = nil
46
- if splat_arg
47
- ret = "
48
- VALUE splat_array = Qnil;
49
- VALUE block_aux = Qnil;
50
- #{to_c(splat_arg[1], "splat_array")};
51
-
52
- if (CLASS_OF(splat_array) == rb_cArray) {
53
- VALUE block_args[_RARRAY_LEN(splat_array) + #{tree.size}];
54
- int i;
55
- #{
56
- (0..tree.size-3).map{|i|
57
- "
58
- #{to_c(tree[i+1], "block_aux")};
59
- block_args[#{i}] = block_aux;
60
- "
61
- }.join(";\n")
62
- };
45
+
46
+ protected_block(false) do
47
+ if splat_arg
48
+ "
49
+ VALUE splat_array = Qnil;
50
+ VALUE block_aux = Qnil;
51
+ #{to_c(splat_arg[1], "splat_array")};
63
52
 
64
- for (i=0; i<_RARRAY_LEN(splat_array); i++) {
65
- block_args[i+#{tree.size-2}] = rb_ary_entry(splat_array,i);
53
+ if (CLASS_OF(splat_array) == rb_cArray) {
54
+ VALUE block_args[_RARRAY_LEN(splat_array) + #{tree.size}];
55
+ int i;
56
+ #{
57
+ (0..tree.size-3).map{|i|
58
+ "
59
+ #{to_c(tree[i+1], "block_aux")};
60
+ block_args[#{i}] = block_aux;
61
+ "
62
+ }.join(";\n")
63
+ };
64
+
65
+ for (i=0; i<_RARRAY_LEN(splat_array); i++) {
66
+ block_args[i+#{tree.size-2}] = rb_ary_entry(splat_array,i);
67
+ }
68
+
69
+ last_expression = #{anonymous_function(&block_code)}((VALUE)pframe, block_args, _RARRAY_LEN(splat_array) + #{tree.size-2});
70
+ } else {
71
+ VALUE block_args[1+#{tree.size}];
72
+ #{
73
+ (0..tree.size-3).map{|i|
74
+ "
75
+ #{to_c(tree[i+1], "block_aux")};
76
+ block_args[#{i}] = block_aux;
77
+ "
78
+ }.join(";\n")
79
+ };
80
+
81
+ block_args[#{tree.size-2}] = splat_array;
82
+ last_expression = #{anonymous_function(&block_code)}((VALUE)pframe, block_args, #{tree.size-1});
66
83
  }
67
84
 
68
- last_expression = #{anonymous_function(&block_code)}((VALUE)pframe, block_args, _RARRAY_LEN(splat_array) + #{tree.size-2});
69
- } else {
70
- VALUE block_args[1+#{tree.size}];
71
- #{
72
- (0..tree.size-3).map{|i|
73
- "
74
- #{to_c(tree[i+1], "block_aux")};
75
- block_args[#{i}] = block_aux;
76
- "
77
- }.join(";\n")
78
- };
79
-
80
- block_args[#{tree.size-2}] = splat_array;
81
- last_expression = #{anonymous_function(&block_code)}((VALUE)pframe, block_args, #{tree.size-1});
82
- }
83
-
84
- "
85
- else
86
- ret = if tree.size > 1
87
- "last_expression = " + anonymous_function(&block_code)+"((VALUE)pframe, (VALUE[]){#{tree[1..-1].map{|subtree| to_c subtree}.join(",")}},#{tree.size-1})"
88
- else
89
- "last_expression = " + anonymous_function(&block_code)+"((VALUE)pframe, (VALUE[]){}, #{tree.size-1})"
90
- end
85
+ "
86
+ else
87
+ if tree.size > 1
88
+ "last_expression = " + anonymous_function(&block_code)+"((VALUE)pframe, (VALUE[]){#{tree[1..-1].map{|subtree| to_c subtree}.join(",")}},#{tree.size-1})"
89
+ else
90
+ "last_expression = " + anonymous_function(&block_code)+"((VALUE)pframe, (VALUE[]){}, #{tree.size-1})"
91
+ end
92
+ end
91
93
  end
92
-
93
- protected_block(ret, false)
94
94
  end
95
95
 
96
96
  define_translator_for(:block, :method => :to_c_block)
@@ -98,24 +98,30 @@ module FastRuby
98
98
  if tree.size == 1
99
99
  return inline_block("return Qnil;")
100
100
  end
101
-
102
- str = ""
103
- str = tree[1..-2].map{ |subtree|
104
- to_c(subtree,"last_expression")
105
- }.join(";")
106
101
 
107
- if tree[-1]
108
- str = str + ";#{to_c(tree[-1],"last_expression")};"
109
- end
110
-
111
- if result_variable
112
- str << "#{result_variable} = last_expression;"
102
+ code = proc{
103
+
104
+ str = tree[1..-2].map{ |subtree|
105
+ to_c(subtree,"last_expression")
106
+ }.join(";")
107
+
108
+ if tree[-1]
109
+ str = str + ";#{to_c(tree[-1],"last_expression")};"
110
+ end
111
+
112
+ if result_variable
113
+ str << "#{result_variable} = last_expression;"
114
+ else
115
+ str << "return last_expression;"
116
+ end
113
117
  str
118
+ }
119
+
120
+ if result_variable
121
+ code.call
114
122
  else
115
- str << "return last_expression;"
116
- inline_block str
123
+ inline_block &code
117
124
  end
118
125
  end
119
-
120
126
  end
121
127
  end
@@ -170,7 +170,7 @@ module FastRuby
170
170
 
171
171
 
172
172
  if block_pass_arg or result_var
173
- code = "
173
+ code = proc{ "
174
174
  {
175
175
  VALUE recv = Qnil;
176
176
  #{to_c recv, "recv"};
@@ -213,8 +213,9 @@ module FastRuby
213
213
  }
214
214
  }
215
215
  "
216
+ }
216
217
 
217
- result_var ? code : inline_block(code)
218
+ result_var ? code.call : inline_block(&code)
218
219
  else
219
220
  "((VALUE(*)(VALUE,VALUE,VALUE,int,VALUE*))#{encode_address(recvtype,signature,mname,tree,inference_complete)})(#{to_c recv}, Qfalse, (VALUE)pframe, 0, (VALUE[]){})"
220
221
  end
@@ -225,7 +226,7 @@ module FastRuby
225
226
 
226
227
  strargs = (0..args_tree.size-2).map{|i| "#{suffix}arg#{i}"}.join(",")
227
228
  if block_pass_arg or result_var
228
- code = "
229
+ code = proc{ "
229
230
  {
230
231
  VALUE recv = Qnil;
231
232
 
@@ -281,7 +282,9 @@ module FastRuby
281
282
 
282
283
  }
283
284
  "
284
- result_var ? code : inline_block(code)
285
+ }
286
+
287
+ result_var ? code.call : inline_block(&code)
285
288
  else
286
289
  strargs = args[1..-1].map{|arg| to_c arg}.join(",")
287
290
  "((VALUE(*)(VALUE,VALUE,VALUE,int,VALUE*))#{encode_address(recvtype,signature,mname,tree,inference_complete)})(#{to_c recv}, Qfalse, (VALUE)pframe, #{args.size-1}, (VALUE[]){#{strargs}})"
@@ -23,73 +23,75 @@ module FastRuby
23
23
 
24
24
  define_translator_for(:rescue, :method => :to_c_rescue, :arity => 1)
25
25
  def to_c_rescue(tree)
26
- if tree[1][0] == :resbody
27
- else_tree = tree[2]
28
-
29
- if else_tree
30
- to_c else_tree
31
- else
32
- "Qnil"
33
- end
34
- else
35
- resbody_tree = tree[2]
36
- else_tree = nil
37
- if tree[-1]
38
- if tree[-1][0] != :resbody
39
- else_tree = tree[-1]
26
+ catch_on_throw do
27
+ if tree[1][0] == :resbody
28
+ else_tree = tree[2]
29
+
30
+ if else_tree
31
+ to_c else_tree
32
+ else
33
+ "Qnil"
40
34
  end
41
- end
42
-
43
- catch_condition_array = []
44
- lasgn_code = ""
45
- resbody_code = to_c(resbody_tree[2])
46
-
47
- rescue_code = ""
48
-
49
- tree[1..-1].each do |resbody_tree|
50
- next if resbody_tree[0] != :resbody
51
-
52
- if resbody_tree[1].size == 1
53
- resbody_tree[1][1] = s(:const, :Exception)
54
- end
55
-
56
- if resbody_tree[1].last[0] == :lasgn
57
- lasgn_code = to_c(resbody_tree[1].last)
35
+ else
36
+ resbody_tree = tree[2]
37
+ else_tree = nil
38
+ if tree[-1]
39
+ if tree[-1][0] != :resbody
40
+ else_tree = tree[-1]
41
+ end
58
42
  end
59
-
60
- resbody_tree[1][1..-1].each do |xtree|
61
- if xtree[0] != :lasgn
62
- trapcode = "rb_eException";
63
-
64
- if xtree
65
- trapcode = to_c(xtree)
43
+
44
+ catch_condition_array = []
45
+ lasgn_code = ""
46
+ resbody_code = to_c(resbody_tree[2])
47
+
48
+ rescue_code = ""
49
+
50
+ tree[1..-1].each do |resbody_tree|
51
+ next if resbody_tree[0] != :resbody
52
+
53
+ if resbody_tree[1].size == 1
54
+ resbody_tree[1][1] = s(:const, :Exception)
55
+ end
56
+
57
+ if resbody_tree[1].last[0] == :lasgn
58
+ lasgn_code = to_c(resbody_tree[1].last)
59
+ end
60
+
61
+ resbody_tree[1][1..-1].each do |xtree|
62
+ if xtree[0] != :lasgn
63
+ trapcode = "rb_eException";
64
+
65
+ if xtree
66
+ trapcode = to_c(xtree)
67
+ end
68
+
69
+ catch_condition_array << "(rb_obj_is_kind_of(frame.thread_data->exception,#{trapcode}) == Qtrue)"
66
70
  end
67
-
68
- catch_condition_array << "(rb_obj_is_kind_of(frame.thread_data->exception,#{trapcode}) == Qtrue)"
69
71
  end
70
- end
71
-
72
- rescue_code << "
73
- if (aux == FASTRUBY_TAG_RAISE) {
74
- if (#{catch_condition_array.join(" || ")})
75
- {
76
- // trap exception
77
- frame.targetted = 1;
78
-
79
- #{lasgn_code};
80
-
81
- #{resbody_code};
72
+
73
+ rescue_code << "
74
+ if (aux == FASTRUBY_TAG_RAISE) {
75
+ if (#{catch_condition_array.join(" || ")})
76
+ {
77
+ // trap exception
78
+ frame.targetted = 1;
79
+
80
+ #{lasgn_code};
81
+
82
+ #{resbody_code};
83
+ }
82
84
  }
83
- }
84
- "
85
+ "
86
+ end
87
+
88
+ frame_call(
89
+ "ret = " + frame(to_c(tree[1])+";","
90
+ #{rescue_code}
91
+ ", else_tree ? to_c(else_tree) : nil, 1)
92
+
93
+ )
85
94
  end
86
-
87
- frame_call(
88
- "ret = " + frame(to_c(tree[1])+";","
89
- #{rescue_code}
90
- ", else_tree ? to_c(else_tree) : nil, 1)
91
-
92
- )
93
95
  end
94
96
  end
95
97
 
@@ -99,9 +101,9 @@ module FastRuby
99
101
  to_c tree[1]
100
102
  else
101
103
  ensured_code = to_c tree[2]
102
- inline_block "
103
- #{frame(to_c(tree[1]),ensured_code,ensured_code,1)};
104
- "
104
+ inline_block {
105
+ "#{frame(to_c(tree[1]),ensured_code,ensured_code,1)};"
106
+ }
105
107
  end
106
108
  end
107
109
 
@@ -31,7 +31,7 @@ module FastRuby
31
31
  infered_value = infer_value(condition_tree)
32
32
  unless infered_value
33
33
 
34
- code = "
34
+ code = proc{"
35
35
  {
36
36
  VALUE condition_result;
37
37
  #{to_c condition_tree, "condition_result"};
@@ -44,12 +44,12 @@ module FastRuby
44
44
  " : ""
45
45
  }
46
46
  }
47
- "
47
+ "}
48
48
 
49
49
  if result_variable_
50
- code
50
+ code.call
51
51
  else
52
- inline_block code + "; return last_expression;"
52
+ inline_block { code.call + "; return last_expression;" }
53
53
  end
54
54
  else
55
55
  if infered_value.value
@@ -70,7 +70,7 @@ module FastRuby
70
70
  begin_while = "begin_while_"+rand(10000000).to_s
71
71
  end_while = "end_while_"+rand(10000000).to_s
72
72
  aux_varname = "_aux_" + rand(10000000).to_s
73
- code = "
73
+ code = proc{ "
74
74
  {
75
75
  VALUE while_condition;
76
76
  VALUE #{aux_varname};
@@ -90,12 +90,12 @@ module FastRuby
90
90
  end
91
91
  }
92
92
  }
93
- "
93
+ "}
94
94
 
95
95
  if result_var
96
- code
96
+ code.call
97
97
  else
98
- inline_block code
98
+ inline_block &code
99
99
  end
100
100
 
101
101
  end
@@ -32,6 +32,7 @@ module FastRuby
32
32
  key_tmp_var = "_key_"+rand(1000000).to_s
33
33
  value_tmp_var = "_value_"+rand(1000000).to_s
34
34
 
35
+ code = proc{
35
36
  hash_aset_code = ""
36
37
  (0..(tree.size-3)/2).each do |i|
37
38
  strkey = to_c tree[1 + i * 2]
@@ -49,7 +50,7 @@ module FastRuby
49
50
  "
50
51
  end
51
52
 
52
- code = "
53
+ "
53
54
  {
54
55
  VALUE #{hash_tmp_var} = rb_hash_new();
55
56
  #{hash_aset_code};
@@ -61,12 +62,12 @@ module FastRuby
61
62
  end
62
63
  };
63
64
  }
64
- "
65
+ "}
65
66
 
66
67
  if result_var
67
- code
68
+ code.call
68
69
  else
69
- inline_block code
70
+ inline_block &code
70
71
  end
71
72
  end
72
73
 
@@ -89,8 +89,8 @@ private
89
89
  alt_locals << local
90
90
  end
91
91
 
92
+ code = proc{
92
93
  fun = nil
93
-
94
94
  locals_scope(alt_locals) do
95
95
  fun = anonymous_function { |method_name| "static VALUE #{method_name}(VALUE self) {
96
96
 
@@ -158,8 +158,8 @@ private
158
158
  "
159
159
  }
160
160
  end
161
-
162
- code = "
161
+
162
+ "
163
163
  {
164
164
  #{init_code}
165
165
 
@@ -168,11 +168,12 @@ private
168
168
  #{fun}(tmpklass);
169
169
  }
170
170
  "
171
+ }
171
172
 
172
173
  if result_var
173
- code + "\n#{result_var} = Qnil;\n"
174
+ code.call + "\n#{result_var} = Qnil;\n"
174
175
  else
175
- inline_block code + "\nreturn Qnil;\n"
176
+ inline_block &code + "\nreturn Qnil;\n"
176
177
  end
177
178
 
178
179
  end
@@ -23,15 +23,16 @@ module FastRuby
23
23
 
24
24
  define_translator_for(:return, :method => :to_c_return)
25
25
  def to_c_return(tree, return_variable = nil)
26
- code = "
26
+ code = proc{"
27
27
  #{to_c(tree[1],"last_expression")};
28
28
  goto local_return;
29
29
  return Qnil;
30
- "
30
+ "}
31
+
31
32
  if return_variable
32
- code
33
+ code.call
33
34
  else
34
- inline_block code
35
+ inline_block &code
35
36
  end
36
37
  end
37
38
 
@@ -40,7 +41,7 @@ module FastRuby
40
41
 
41
42
  value_tmp_var = "value_" + rand(10000000).to_s
42
43
 
43
- code = "
44
+ code = proc{"
44
45
 
45
46
  {
46
47
  VALUE #{value_tmp_var} = Qnil;
@@ -65,10 +66,10 @@ module FastRuby
65
66
  longjmp(pframe->jmp,FASTRUBY_TAG_BREAK);
66
67
 
67
68
  }
68
- "
69
+ "}
69
70
 
70
71
  if result_var
71
- code
72
+ code.call
72
73
  else
73
74
  inline_block code
74
75
  end
@@ -117,7 +118,7 @@ module FastRuby
117
118
  def to_c_next(tree, result_var = nil)
118
119
  tmp_varname = "_acc_" + rand(10000000).to_s
119
120
  if @on_block
120
- code = "
121
+ code =proc {"
121
122
  {
122
123
  last_expression = Qnil;
123
124
 
@@ -129,15 +130,156 @@ module FastRuby
129
130
  pframe->thread_data->accumulator = last_expression;
130
131
  goto fastruby_local_next;
131
132
  }
132
- "
133
+ "}
134
+
133
135
  if result_var
134
- code
136
+ code.call
135
137
  else
136
- inline_block code
138
+ inline_block &code
137
139
  end
138
140
  else
139
141
  _raise("rb_eLocalJumpError","illegal next");
140
142
  end
141
143
  end
144
+
145
+ define_method_handler(:to_c, :priority => 100) { |tree, result_var = nil|
146
+
147
+ call_tree = tree[1]
148
+ catch_tag_id = call_tree[3][1][1]
149
+ included_catch_jmp = false
150
+
151
+ @catch_jmp = @catch_jmp || Set.new
152
+
153
+ begin
154
+ inner_code = catch_block(catch_tag_id) do
155
+ to_c(tree[3],result_var)
156
+ end
157
+
158
+ included_catch_jmp = true if @catch_jmp.include?(catch_tag_id)
159
+ ensure
160
+ @catch_jmp.delete(catch_tag_id)
161
+ end
162
+
163
+ if included_catch_jmp
164
+ new_frame = anonymous_function{ |name| "
165
+ static VALUE #{name}(VALUE param) {
166
+ volatile VALUE last_expression = Qnil;
167
+ #{@frame_struct} frame;
168
+
169
+ typeof(frame)* volatile pframe;
170
+ typeof(frame)* volatile parent_frame;
171
+ #{@locals_struct}* volatile plocals;
172
+
173
+ parent_frame = (void*)param;
174
+
175
+ frame.parent_frame = (void*)param;
176
+ frame.plocals = parent_frame->plocals;
177
+ frame.rescue = parent_frame->rescue;
178
+ frame.targetted = 0;
179
+ frame.thread_data = parent_frame->thread_data;
180
+ frame.return_value = Qnil;
181
+ frame.thread_data->accumulator = Qnil;
182
+ if (frame.thread_data == 0) frame.thread_data = rb_current_thread_data();
183
+
184
+ plocals = frame.plocals;
185
+ pframe = &frame;
186
+
187
+ volatile int aux = setjmp(frame.jmp);
188
+ if (aux != 0) {
189
+ // restore previous frame
190
+ typeof(pframe) original_frame = pframe;
191
+ pframe = parent_frame;
192
+
193
+ if (aux == (int)#{intern_num catch_tag_id.to_s + "_end"}) {
194
+ return frame.thread_data->accumulator;
195
+ } else if (aux == (int)#{intern_num catch_tag_id.to_s + "_start"}) {
196
+ } else {
197
+ longjmp(pframe->jmp,aux);
198
+ }
199
+
200
+ return last_expression;
201
+ }
202
+
203
+ #{catch_tag_id.to_s}_start:
204
+ #{inner_code};
205
+ #{catch_tag_id.to_s}_end:
206
+ return last_expression;
207
+ #{@catch_blocks.map { |cb|
208
+ "#{cb.to_s}_end:
209
+
210
+ plocals->return_value = last_expression;
211
+ plocals->targetted = 1;
212
+ longjmp(pframe->jmp, #{intern_num( cb.to_s + "_end")});
213
+
214
+ #{cb.to_s}_start:
215
+
216
+ plocals->return_value = last_expression;
217
+ plocals->targetted = 1;
218
+ longjmp(pframe->jmp, #{intern_num( cb.to_s + "_start")});
219
+
220
+ "
221
+
222
+ }.join("\n")
223
+ }
224
+
225
+ }
226
+ "
227
+ } + "((VALUE)pframe)"
228
+
229
+ if result_var
230
+ "#{result_var} = #{new_frame};"
231
+ else
232
+ new_frame
233
+ end
234
+ else
235
+ "
236
+ #{catch_tag_id.to_s}_start:
237
+ #{inner_code};
238
+ #{catch_tag_id.to_s}_end:
239
+
240
+ "
241
+ end
242
+
243
+ }.condition{|tree, result_var = nil|
244
+ tree.node_type == :iter && tree[1][2] == :_catch
245
+ }
246
+
247
+ define_method_handler(:to_c, :priority => 100) { |tree, result_var = nil|
248
+ code = ""
249
+
250
+ catch_tag_id = tree[3][1][1]
251
+
252
+ if @catch_jmp_on_throw
253
+ @catch_jmp << catch_tag_id
254
+ end
255
+
256
+ code << to_c(tree[3][2] || fs(:nil), "last_expression")
257
+ code << "pframe->thread_data->accumulator = last_expression;"
258
+ code << "goto #{catch_tag_id.to_s}_end;"
259
+
260
+ if result_var
261
+ code
262
+ else
263
+ inline_block code
264
+ end
265
+ }.condition{|tree, result_var = nil|
266
+ tree.node_type == :call && tree[2] == :_throw
267
+ }
268
+
269
+ define_method_handler(:to_c, :priority => 100) { |tree, result_var = nil|
270
+ code = ""
271
+
272
+ catch_tag_id = tree[3][1][1]
273
+ code << "goto #{catch_tag_id.to_s}_start;"
274
+
275
+ if result_var
276
+ code
277
+ else
278
+ inline_block code
279
+ end
280
+ }.condition{|tree, result_var = nil|
281
+ tree.node_type == :call && tree[2] == :_loop
282
+ }
283
+
142
284
  end
143
285
  end