fastruby 0.0.21 → 0.0.22

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 (49) hide show
  1. data/Rakefile +1 -1
  2. data/benchmarks/benchmark.rb +3 -0
  3. data/benchmarks/benchmark.rb~ +3 -12
  4. data/benchmarks/benchmark8.rb +48 -0
  5. data/benchmarks/benchmark8.rb~ +46 -0
  6. data/lib/fastruby.rb +2 -1
  7. data/lib/fastruby.rb~ +2 -1
  8. data/lib/fastruby/builder.rb +18 -1
  9. data/lib/fastruby/builder.rb~ +18 -5
  10. data/lib/fastruby/modules/lvar_type/lasgn.rb~ +41 -0
  11. data/lib/fastruby/modules/translator/block.rb +1 -1
  12. data/lib/fastruby/modules/translator/block.rb~ +128 -0
  13. data/lib/fastruby/modules/translator/call.rb +62 -139
  14. data/lib/fastruby/modules/translator/call.rb~ +61 -140
  15. data/lib/fastruby/modules/translator/defn.rb +49 -105
  16. data/lib/fastruby/modules/translator/defn.rb~ +211 -0
  17. data/lib/fastruby/modules/translator/exceptions.rb +1 -0
  18. data/lib/fastruby/modules/translator/exceptions.rb~ +120 -0
  19. data/lib/fastruby/modules/translator/iter.rb +13 -20
  20. data/lib/fastruby/modules/translator/iter.rb~ +738 -0
  21. data/lib/fastruby/modules/translator/literal.rb +8 -1
  22. data/lib/fastruby/modules/translator/literal.rb~ +157 -0
  23. data/lib/fastruby/modules/translator/nonlocal.rb +7 -0
  24. data/lib/fastruby/modules/translator/nonlocal.rb~ +304 -0
  25. data/lib/fastruby/modules/translator/static.rb +1 -0
  26. data/lib/fastruby/modules/translator/static.rb~ +290 -0
  27. data/lib/fastruby/modules/translator/variable.rb +24 -6
  28. data/lib/fastruby/modules/translator/variable.rb~ +298 -0
  29. data/lib/fastruby/translator/translator.rb +411 -284
  30. data/lib/fastruby/translator/translator.rb~ +1728 -0
  31. data/spec/fastruby_only/base_spec.rb~ +74 -0
  32. data/spec/ruby/base_spec.rb~ +1 -338
  33. data/spec/ruby/block/break_spec.rb~ +21 -0
  34. data/spec/ruby/block/callcc_spec.rb~ +236 -0
  35. data/spec/ruby/block/lambda_spec.rb~ +1 -178
  36. data/spec/ruby/block/next_spec.rb~ +85 -0
  37. data/spec/ruby/block/proc_spec.rb~ +22 -0
  38. data/spec/ruby/block/redo_spec.rb~ +133 -0
  39. data/spec/ruby/block/retry_spec.rb~ +135 -0
  40. data/spec/ruby/block_spec.rb~ +494 -2
  41. data/spec/ruby/call/base_call_spec.rb~ +60 -2
  42. data/spec/ruby/defn/default_args_spec.rb~ +303 -0
  43. data/spec/ruby/defn/multiple_args_spec.rb~ +317 -0
  44. data/spec/ruby/defn/replacement_spec.rb +29 -1
  45. data/spec/ruby/defn/replacement_spec.rb~ +52 -21
  46. data/spec/ruby/exception/internal_ex_spec.rb~ +2 -2
  47. data/spec/ruby/variable_spec.rb~ +46 -23
  48. data/spec/static/flow_spec.rb~ +48 -0
  49. metadata +34 -12
@@ -106,7 +106,14 @@ module FastRuby
106
106
  end
107
107
  end
108
108
 
109
- define_translator_for(:self, :arity => 1){|*x| tree = x.first; locals_accessor + "self"}
109
+ define_translator_for(:self, :arity => 1){|*x| tree = x.first;
110
+ if @has_inline_block
111
+ locals_accessor + "self"
112
+ else
113
+ "self"
114
+ end
115
+ }
116
+
110
117
  define_translator_for(:false, :arity => 1){|*x| "Qfalse"}
111
118
  define_translator_for(:true, :arity => 1){|*x| "Qtrue"}
112
119
 
@@ -0,0 +1,157 @@
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
+
24
+ define_translator_for(:lit, :arity => 1){|*x| tree = x.first; literal_value tree[1]}
25
+ define_translator_for(:nil, :arity => 1){|*x| tree = x.first; "Qnil"}
26
+ define_translator_for(:str, :arity => 1){|*x| tree = x.first; literal_value tree[1]}
27
+
28
+ define_translator_for(:hash, :method => :to_c_hash)
29
+ def to_c_hash(tree, result_var = nil)
30
+
31
+ hash_tmp_var = "_hash_"+rand(1000000).to_s
32
+ key_tmp_var = "_key_"+rand(1000000).to_s
33
+ value_tmp_var = "_value_"+rand(1000000).to_s
34
+
35
+ code = proc{
36
+ hash_aset_code = ""
37
+ (0..(tree.size-3)/2).each do |i|
38
+ strkey = to_c tree[1 + i * 2]
39
+ strvalue = to_c tree[2 + i * 2]
40
+ hash_aset_code << "
41
+ {
42
+ VALUE #{key_tmp_var} = Qnil;
43
+ VALUE #{value_tmp_var} = Qnil;
44
+
45
+ #{to_c tree[1 + i * 2], key_tmp_var};
46
+ #{to_c tree[2 + i * 2], value_tmp_var};
47
+
48
+ rb_hash_aset(#{hash_tmp_var}, #{key_tmp_var}, #{value_tmp_var});
49
+ }
50
+ "
51
+ end
52
+
53
+ "
54
+ {
55
+ VALUE #{hash_tmp_var} = rb_hash_new();
56
+ #{hash_aset_code};
57
+ #{
58
+ if result_var
59
+ "#{result_var} = #{hash_tmp_var}"
60
+ else
61
+ "return #{hash_tmp_var}"
62
+ end
63
+ };
64
+ }
65
+ "}
66
+
67
+ if result_var
68
+ code.call
69
+ else
70
+ inline_block &code
71
+ end
72
+ end
73
+
74
+ define_translator_for(:array, :method => :to_c_array)
75
+ def to_c_array(tree, result_var = nil)
76
+ if tree.size > 1
77
+ if result_var
78
+ prefix = "_array_element_" + rand(10000000).to_s + "_"
79
+ "
80
+ {
81
+ #{
82
+ (0..tree.size-2).map{|x|
83
+ "VALUE #{prefix}#{x};"
84
+ }.join("\n");
85
+ }
86
+
87
+ #{
88
+ (0..tree.size-2).map{|x|
89
+ to_c(tree[x+1], prefix+x.to_s)
90
+ }.join("\n");
91
+ }
92
+
93
+ #{result_var} = rb_ary_new3(#{tree.size-1}, #{(0..tree.size-2).map{|x| prefix+x.to_s}.join(",")} );
94
+ }
95
+ "
96
+ else
97
+ strargs = tree[1..-1].map{|subtree| to_c subtree}.join(",")
98
+ "rb_ary_new3(#{tree.size-1}, #{strargs})"
99
+ end
100
+ else
101
+ if result_var
102
+ "#{result_var} = rb_ary_new3(0);"
103
+ else
104
+ "rb_ary_new3(0)"
105
+ end
106
+ end
107
+ end
108
+
109
+ define_translator_for(:self, :arity => 1){|*x| tree = x.first;
110
+ if @has_inline_block
111
+ locals_accessor + "self"
112
+ else
113
+
114
+ end
115
+ }
116
+
117
+ define_translator_for(:false, :arity => 1){|*x| "Qfalse"}
118
+ define_translator_for(:true, :arity => 1){|*x| "Qtrue"}
119
+
120
+ define_translator_for(:dot2, :method => :to_c_dot2)
121
+ def to_c_dot2(tree, result_var = nil)
122
+
123
+ begin_var = "_begin"+rand(10000000).to_s
124
+ end_var = "_end"+rand(10000000).to_s
125
+
126
+ if result_var
127
+ "
128
+ {
129
+ VALUE #{begin_var} = Qnil;
130
+ VALUE #{end_var} = Qnil;
131
+
132
+ #{to_c tree[1], begin_var};
133
+ #{to_c tree[2], end_var};
134
+
135
+ #{result_var} = rb_range_new(#{begin_var}, #{end_var},0);
136
+ }
137
+ "
138
+ else
139
+ if result_var
140
+ "
141
+ {
142
+ VALUE #{begin_var} = Qnil;
143
+ VALUE #{end_var} = Qnil;
144
+ #{to_c tree[1], begin_var};
145
+ #{to_c tree[2], end_var};
146
+
147
+ #{result_var} = rb_range_new(#{begin_var}, #{end_var},0)
148
+ }
149
+ "
150
+ else
151
+ "rb_range_new(#{to_c tree[1]}, #{to_c tree[2]},0)"
152
+ end
153
+ end
154
+ end
155
+
156
+ end
157
+ end
@@ -23,6 +23,7 @@ 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
+ @has_nonlocal_goto = true
26
27
  code = proc{"
27
28
  #{to_c(tree[1],"last_expression")};
28
29
  goto local_return;
@@ -38,6 +39,7 @@ module FastRuby
38
39
 
39
40
  define_translator_for(:break, :method => :to_c_break)
40
41
  def to_c_break(tree, result_var = nil)
42
+ @has_nonlocal_goto = true
41
43
 
42
44
  value_tmp_var = "value_" + rand(10000000).to_s
43
45
 
@@ -77,6 +79,7 @@ module FastRuby
77
79
 
78
80
  define_translator_for(:retry, :method => :to_c_retry)
79
81
  def to_c_retry(tree, result_var = nil)
82
+ @has_nonlocal_goto = true
80
83
  code = "
81
84
  {
82
85
  typeof(pframe) target_frame_;
@@ -99,6 +102,7 @@ module FastRuby
99
102
 
100
103
  define_translator_for(:redo, :method => :to_c_redo)
101
104
  def to_c_redo(tree, result_var = nil)
105
+ @has_nonlocal_goto = true
102
106
  if @on_block
103
107
  code = "
104
108
  goto fastruby_local_redo;
@@ -116,6 +120,7 @@ module FastRuby
116
120
 
117
121
  define_translator_for(:next, :method => :to_c_next)
118
122
  def to_c_next(tree, result_var = nil)
123
+ @has_nonlocal_goto = true
119
124
  tmp_varname = "_acc_" + rand(10000000).to_s
120
125
  if @on_block
121
126
  code =proc {"
@@ -249,6 +254,7 @@ module FastRuby
249
254
  }
250
255
 
251
256
  define_method_handler(:to_c, :priority => 100) { |*x|
257
+ @has_nonlocal_goto = true
252
258
  tree, result_var = x
253
259
 
254
260
  code = ""
@@ -275,6 +281,7 @@ module FastRuby
275
281
  }
276
282
 
277
283
  define_method_handler(:to_c, :priority => 100) { |*x|
284
+ @has_nonlocal_goto = true
278
285
  tree, result_var = x
279
286
 
280
287
  code = ""
@@ -0,0 +1,304 @@
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
+
24
+ define_translator_for(:return, :method => :to_c_return)
25
+ def to_c_return(tree, return_variable = nil)
26
+ @has_nonlocal_goto = true
27
+ code = proc{"
28
+ #{to_c(tree[1],"last_expression")};
29
+ goto local_return;
30
+ return Qnil;
31
+ "}
32
+
33
+ if return_variable
34
+ code.call
35
+ else
36
+ inline_block &code
37
+ end
38
+ end
39
+
40
+ define_translator_for(:break, :method => :to_c_break)
41
+ def to_c_break(tree, result_var = nil)
42
+ @has_nonlocal_goto = true
43
+
44
+ value_tmp_var = "value_" + rand(10000000).to_s
45
+
46
+ code = proc{"
47
+
48
+ {
49
+ VALUE #{value_tmp_var} = Qnil;
50
+ #{
51
+ if tree[1]
52
+ to_c(tree[1], value_tmp_var)
53
+ end
54
+ };
55
+
56
+ typeof(pframe) target_frame_;
57
+ target_frame_ = (void*)plocals->call_frame;
58
+
59
+ if (target_frame_ == 0) {
60
+ #{_raise("rb_eLocalJumpError","illegal break")};
61
+ }
62
+
63
+ plocals->call_frame = 0;
64
+
65
+ target_frame_->return_value = #{value_tmp_var};
66
+ target_frame_->targetted = 1;
67
+ pframe->thread_data->exception = Qnil;
68
+ longjmp(pframe->jmp,FASTRUBY_TAG_BREAK);
69
+
70
+ }
71
+ "}
72
+
73
+ if result_var
74
+ code.call
75
+ else
76
+ inline_block code
77
+ end
78
+ end
79
+
80
+ define_translator_for(:retry, :method => :to_c_retry)
81
+ def to_c_retry(tree, result_var = nil)
82
+ @has_nonlocal_goto = true
83
+ code = "
84
+ {
85
+ typeof(pframe) target_frame_;
86
+ target_frame_ = (void*)plocals->call_frame;
87
+
88
+ if (target_frame_ == 0) {
89
+ #{_raise("rb_eLocalJumpError","illegal retry")};
90
+ }
91
+
92
+ target_frame_->targetted = 1;
93
+ longjmp(pframe->jmp,FASTRUBY_TAG_RETRY);
94
+ }
95
+ "
96
+ if result_var
97
+ code
98
+ else
99
+ inline_block code
100
+ end
101
+ end
102
+
103
+ define_translator_for(:redo, :method => :to_c_redo)
104
+ def to_c_redo(tree, result_var = nil)
105
+ has_nonlocal_goto = true
106
+ if @on_block
107
+ code = "
108
+ goto fastruby_local_redo;
109
+ "
110
+
111
+ if result_var
112
+ code
113
+ else
114
+ inline_block code
115
+ end
116
+ else
117
+ _raise("rb_eLocalJumpError","illegal redo");
118
+ end
119
+ end
120
+
121
+ define_translator_for(:next, :method => :to_c_next)
122
+ def to_c_next(tree, result_var = nil)
123
+ has_nonlocal_goto = true
124
+ tmp_varname = "_acc_" + rand(10000000).to_s
125
+ if @on_block
126
+ code =proc {"
127
+ {
128
+ last_expression = Qnil;
129
+
130
+ #{
131
+ if tree[1]
132
+ to_c(tree[1],"last_expression")
133
+ end
134
+ }
135
+ pframe->thread_data->accumulator = last_expression;
136
+ goto fastruby_local_next;
137
+ }
138
+ "}
139
+
140
+ if result_var
141
+ code.call
142
+ else
143
+ inline_block &code
144
+ end
145
+ else
146
+ _raise("rb_eLocalJumpError","illegal next");
147
+ end
148
+ end
149
+
150
+ define_method_handler(:to_c, :priority => 100) { |*x|
151
+ tree, result_var = x
152
+
153
+
154
+ call_tree = tree[1]
155
+ catch_tag_id = call_tree[3][1][1]
156
+ included_catch_jmp = false
157
+
158
+ @catch_jmp = @catch_jmp || Set.new
159
+
160
+ begin
161
+ inner_code = catch_block(catch_tag_id) do
162
+ to_c(tree[3],result_var)
163
+ end
164
+
165
+ included_catch_jmp = true if @catch_jmp.include?(catch_tag_id)
166
+ ensure
167
+ @catch_jmp.delete(catch_tag_id)
168
+ end
169
+
170
+ if included_catch_jmp
171
+ new_frame = anonymous_function{ |name| "
172
+ static VALUE #{name}(VALUE param) {
173
+ volatile VALUE last_expression = Qnil;
174
+ #{@frame_struct} frame;
175
+
176
+ typeof(frame)* volatile pframe;
177
+ typeof(frame)* volatile parent_frame;
178
+ #{@locals_struct}* volatile plocals;
179
+
180
+ parent_frame = (void*)param;
181
+
182
+ frame.parent_frame = (void*)param;
183
+ frame.plocals = parent_frame->plocals;
184
+ frame.rescue = parent_frame->rescue;
185
+ frame.targetted = 0;
186
+ frame.thread_data = parent_frame->thread_data;
187
+ frame.return_value = Qnil;
188
+ frame.thread_data->accumulator = Qnil;
189
+ if (frame.thread_data == 0) frame.thread_data = rb_current_thread_data();
190
+
191
+ plocals = frame.plocals;
192
+ pframe = &frame;
193
+
194
+ volatile int aux = setjmp(frame.jmp);
195
+ if (aux != 0) {
196
+ // restore previous frame
197
+ typeof(pframe) original_frame = pframe;
198
+ pframe = parent_frame;
199
+
200
+ if (aux == (int)#{intern_num catch_tag_id.to_s + "_end"}) {
201
+ return frame.thread_data->accumulator;
202
+ } else if (aux == (int)#{intern_num catch_tag_id.to_s + "_start"}) {
203
+ } else {
204
+ longjmp(pframe->jmp,aux);
205
+ }
206
+
207
+ return last_expression;
208
+ }
209
+
210
+ #{catch_tag_id.to_s}_start:
211
+ #{inner_code};
212
+ #{catch_tag_id.to_s}_end:
213
+ return last_expression;
214
+ #{@catch_blocks.map { |cb|
215
+ "#{cb.to_s}_end:
216
+
217
+ plocals->return_value = last_expression;
218
+ plocals->targetted = 1;
219
+ longjmp(pframe->jmp, #{intern_num( cb.to_s + "_end")});
220
+
221
+ #{cb.to_s}_start:
222
+
223
+ plocals->return_value = last_expression;
224
+ plocals->targetted = 1;
225
+ longjmp(pframe->jmp, #{intern_num( cb.to_s + "_start")});
226
+
227
+ "
228
+
229
+ }.join("\n")
230
+ }
231
+
232
+ }
233
+ "
234
+ } + "((VALUE)pframe)"
235
+
236
+ if result_var
237
+ "#{result_var} = #{new_frame};"
238
+ else
239
+ new_frame
240
+ end
241
+ else
242
+ "
243
+ #{catch_tag_id.to_s}_start:
244
+ #{inner_code};
245
+ #{catch_tag_id.to_s}_end:
246
+
247
+ "
248
+ end
249
+
250
+ }.condition{|*x|
251
+ tree, result_var = x
252
+
253
+ tree.node_type == :iter && tree[1][2] == :_catch
254
+ }
255
+
256
+ define_method_handler(:to_c, :priority => 100) { |*x|
257
+ @has_nonlocal_goto = true
258
+ tree, result_var = x
259
+
260
+ code = ""
261
+
262
+ catch_tag_id = tree[3][1][1]
263
+
264
+ if @catch_jmp_on_throw
265
+ @catch_jmp << catch_tag_id
266
+ end
267
+
268
+ code << to_c(tree[3][2] || fs(:nil), "last_expression")
269
+ code << "pframe->thread_data->accumulator = last_expression;"
270
+ code << "goto #{catch_tag_id.to_s}_end;"
271
+
272
+ if result_var
273
+ code
274
+ else
275
+ inline_block code
276
+ end
277
+ }.condition{|*x|
278
+ tree, result_var = x
279
+
280
+ tree.node_type == :call && tree[2] == :_throw
281
+ }
282
+
283
+ define_method_handler(:to_c, :priority => 100) { |*x|
284
+ @has_nonlocal_goto = true
285
+ tree, result_var = x
286
+
287
+ code = ""
288
+
289
+ catch_tag_id = tree[3][1][1]
290
+ code << "goto #{catch_tag_id.to_s}_start;"
291
+
292
+ if result_var
293
+ code
294
+ else
295
+ inline_block code
296
+ end
297
+ }.condition{|*x|
298
+ tree, result_var = x
299
+
300
+ tree.node_type == :call && tree[2] == :_loop
301
+ }
302
+
303
+ end
304
+ end