fastruby 0.0.21 → 0.0.22

Sign up to get free protection for your applications and to get access to all the features.
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