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
@@ -79,7 +79,7 @@ module FastRuby
79
79
  recvtype = infer_type(recv)
80
80
 
81
81
  if args.size > 1
82
- if (not recvtype) or args.last[0] == :splat or (not RUBY_VERSION =~ /^1\\.9/)
82
+ if (not recvtype) or args.last[0] == :splat or (not RUBY_VERSION =~ /^1\.9/)
83
83
  if block_pass_arg
84
84
  call_tree = tree.dup
85
85
  call_tree[3] = args.select{|arg| if arg == :arglist
@@ -152,55 +152,37 @@ module FastRuby
152
152
  end
153
153
  end
154
154
  end
155
+
156
+ signature = if recvtype
157
+ [recvtype]
158
+ else
159
+ [nil]
160
+ end
161
+
162
+ args[1..-1].each do |arg|
163
+ argtype = infer_type(arg)
164
+ signature << argtype
165
+ end
166
+
167
+ if block_pass_arg
155
168
 
156
- if recvtype
157
-
158
- address = nil
159
- mobject = nil
160
-
161
- inference_complete = true
162
- signature = [recvtype]
163
-
164
- args[1..-1].each do |arg|
165
- argtype = infer_type(arg)
166
- signature << argtype
167
- unless argtype
168
- inference_complete = false
169
- end
170
- end
171
-
172
- if repass_var
173
- extraargs = ","+repass_var
174
- extraargs_signature = ",VALUE " + repass_var
175
- else
176
- extraargs = ""
177
- extraargs_signature = ""
178
- end
179
-
180
- block_proc_tree = s(:call, block_pass_arg[1], :to_proc, s(:arglist)) if block_pass_arg
181
-
182
- block_wrapping_proc = proc { |name| "
183
- static VALUE #{name}(int argc, VALUE* argv, VALUE _locals, VALUE _parent_frame) {
184
- return rb_proc_call(_locals, rb_ary_new4(argc, argv));
185
- }
186
- "
169
+ block_proc_tree = s(:call, block_pass_arg[1], :to_proc, s(:arglist))
170
+ block_wrapping_proc = proc { |name| "
171
+ static VALUE #{name}(int argc, VALUE* argv, VALUE _locals, VALUE _parent_frame) {
172
+ return rb_proc_call(_locals, rb_ary_new4(argc, argv));
187
173
  }
188
-
174
+ "
175
+ }
176
+
177
+ code = inline_block do
189
178
  if argnum == 0
190
- value_cast = "VALUE,VALUE,VALUE"
191
-
192
-
193
- if block_pass_arg or result_var
194
- code = proc{ "
195
- {
196
- VALUE recv = Qnil;
197
- #{to_c recv, "recv"};
198
-
199
- #{@block_struct} block, *pblock = Qfalse;
179
+ "
180
+ #{@block_struct} block, *pblock = Qfalse;
181
+
182
+ VALUE proc = Qnil;
183
+ VALUE recv = Qnil;
200
184
 
201
- #{if block_pass_arg
202
- "
203
- VALUE proc = Qnil;
185
+ #{to_c(recv, "recv")}
204
186
  #{to_c(block_proc_tree, "proc") }
205
187
 
206
188
  VALUE block_address_value = rb_ivar_get(proc, #{intern_num "__block_address"});
@@ -217,61 +199,21 @@ module FastRuby
217
199
  block.proc = proc;
218
200
  pblock = &block;
219
201
  }
220
-
221
- "
222
- end
223
- }
224
-
225
- #{if result_var
226
- "
227
- #{result_var} = ((VALUE(*)(VALUE,VALUE,VALUE,int,VALUE*))#{encode_address(recvtype,signature,mname,tree,inference_complete)})(recv, (VALUE)pblock, (VALUE)pframe, 0, (VALUE[]){});
228
- "
229
- else
230
- "
231
- ((VALUE(*)(VALUE,VALUE,VALUE,int,VALUE*))#{encode_address(recvtype,signature,mname,tree,inference_complete)})(recv, (VALUE)pblock, (VALUE)pframe, 0, (VALUE[]){});
232
- "
233
- end
234
- }
235
- }
236
- "
237
- }
238
-
239
- result_var ? code.call : inline_block(&code)
240
- else
241
- "((VALUE(*)(VALUE,VALUE,VALUE,int,VALUE*))#{encode_address(recvtype,signature,mname,tree,inference_complete)})(#{to_c recv}, Qfalse, (VALUE)pframe, 0, (VALUE[]){})"
242
- end
243
-
202
+
203
+ return #{dynamic_call(signature,mname)}(recv, (void*)pblock, (void*)pframe, 0, (VALUE[]){});"
244
204
  else
245
- value_cast = ( ["VALUE"]*(args.size) ).join(",") + ",VALUE,VALUE"
246
- suffix = "_" + rand(1000000).to_s+"_"
247
-
248
- strargs = (0..args_tree.size-2).map{|i| "#{suffix}arg#{i}"}.join(",")
249
- if block_pass_arg or result_var
250
- code = proc{ "
251
- {
252
- VALUE recv = Qnil;
253
-
254
- #{
255
- (0..args_tree.size-2).map{ |x|
256
- "VALUE #{suffix}arg#{x};"
257
- }.join("\n")
258
- }
259
-
260
- #{
261
- (0..args_tree.size-2).map{ |x|
262
- to_c(args_tree[x+1], "#{suffix}arg#{x}") + ";"
263
- }.join("\n")
264
- }
265
-
266
- #{to_c recv, "recv"};
267
-
268
- #{@block_struct} block, *pblock = Qfalse;
205
+ strargs = args[1..-1].map{|arg| to_c arg}.join(",")
206
+ "
207
+ #{@block_struct} block, *pblock = Qfalse;
208
+
209
+ VALUE proc = Qnil;
210
+ VALUE recv = Qnil;
269
211
 
270
- #{if block_pass_arg
271
- "
272
- VALUE proc = Qnil;
212
+ #{to_c(recv, "recv")}
273
213
  #{to_c(block_proc_tree, "proc") }
214
+
274
215
  VALUE block_address_value = rb_ivar_get(proc, #{intern_num "__block_address"});
216
+
275
217
  if (block_address_value != Qnil) {
276
218
  block.block_function_address = NUM2PTR(block_address_value);
277
219
  block.block_function_param = NUM2PTR(rb_ivar_get(proc, #{intern_num "__block_param"}));
@@ -284,56 +226,35 @@ module FastRuby
284
226
  block.proc = proc;
285
227
  pblock = &block;
286
228
  }
287
-
288
- "
289
- end
290
- }
291
-
292
- #{if result_var
293
- "
294
- #{result_var} = ((VALUE(*)(VALUE,VALUE,VALUE,int,VALUE*))#{encode_address(recvtype,signature,mname,tree,inference_complete)})(recv, (VALUE)pblock, (VALUE)pframe, #{args.size-1}, (VALUE[]){#{strargs}});
295
- "
296
- else
297
- "
298
- ((VALUE(*)(VALUE,VALUE,VALUE,int,VALUE*))#{encode_address(recvtype,signature,mname,tree,inference_complete)})(recv, (VALUE)pblock, (VALUE)pframe, #{args.size-1}, (VALUE[]){#{strargs}});
299
- "
300
- end
301
- }
302
-
303
-
304
- }
305
- "
306
- }
307
-
308
- result_var ? code.call : inline_block(&code)
309
- else
310
- strargs = args[1..-1].map{|arg| to_c arg}.join(",")
311
- "((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}})"
312
- end
229
+
230
+
231
+ return #{dynamic_call(signature,mname)}(recv, (void*)pblock, (void*)pframe, #{args.size-1}, (VALUE[]){#{strargs}});"
313
232
  end
314
-
315
- else # else recvtype
316
- if argnum == 0
317
- code = protected_block("last_expression = rb_funcall(#{to_c recv}, #{intern_num tree[2]}, 0)", true, repass_var)
318
- if result_var
233
+ end
234
+
235
+ return (if result_var
319
236
  "
320
- #{result_var} = #{code};
237
+ #{result_var} = #{code};
321
238
  "
322
- else
323
- code
324
- end
239
+ else
240
+ code
241
+ end)
242
+ else
243
+ code = if argnum == 0
244
+ "#{dynamic_call(signature,mname)}(#{to_c recv}, (void*)Qfalse, (void*)pframe, 0, (VALUE[]){})"
325
245
  else
326
246
  strargs = args[1..-1].map{|arg| to_c arg}.join(",")
327
- code = protected_block("last_expression = rb_funcall(#{to_c recv}, #{intern_num tree[2]}, #{argnum}, #{strargs} )", true, repass_var)
328
- if result_var
247
+ "#{dynamic_call(signature,mname)}(#{to_c recv}, (void*)Qfalse, (void*)pframe, #{args.size-1}, (VALUE[]){#{strargs}})"
248
+ end
249
+
250
+ return (if result_var
329
251
  "
330
- #{result_var} = #{code};
252
+ #{result_var} = #{code};
331
253
  "
332
- else
333
- code
334
- end
335
- end
336
- end # if recvtype
254
+ else
255
+ code
256
+ end)
257
+ end
337
258
  end
338
259
 
339
260
  define_translator_for(:call, :method => :to_c_attrasgn, :arity => 1)
@@ -43,14 +43,14 @@ module FastRuby
43
43
  code = "
44
44
 
45
45
 
46
- if (rb_obj_is_kind_of(plocals->self, rb_cClass) || rb_obj_is_kind_of(plocals->self, rb_cModule)) {
46
+ if (rb_obj_is_kind_of(#{locals_accessor}self, rb_cClass) || rb_obj_is_kind_of(#{locals_accessor}self, rb_cModule)) {
47
47
 
48
48
  #{unless options[:fastruby_only]
49
49
  "rb_define_method(plocals->self, #{method_name.to_s.inspect}, #{anonymous_method_name}, -1);"
50
50
  end
51
51
  }
52
52
 
53
- #{global_klass_variable} = plocals->self;
53
+ #{global_klass_variable} = #{locals_accessor}self;
54
54
  // set tree
55
55
  rb_funcall(#{literal_value FastRuby}, #{intern_num :set_tree}, 4,
56
56
  #{global_klass_variable},
@@ -61,7 +61,7 @@ module FastRuby
61
61
  );
62
62
 
63
63
  } else {
64
- VALUE obj = plocals->self;
64
+ VALUE obj = #{locals_accessor}self;
65
65
  rb_define_singleton_method(obj, #{method_name.to_s.inspect}, #{anonymous_method_name}, -1 );
66
66
 
67
67
  #{global_klass_variable} = CLASS_OF(obj);
@@ -147,120 +147,64 @@ private
147
147
  def anonymous_dispatcher(global_klass_variable, method_name)
148
148
 
149
149
  strmethodargs = "self,block,(VALUE)&frame"
150
-
150
+ nilsignature = [nil]*32
151
+
151
152
  anonymous_function{ |anonymous_method_name| "VALUE #{anonymous_method_name}(int argc_, VALUE* argv, VALUE self) {
152
- VALUE klass = #{global_klass_variable};
153
- char method_name[argc_*40+64];
153
+ struct {
154
+ void* parent_frame;
155
+ void* plocals;
156
+ jmp_buf jmp;
157
+ VALUE return_value;
158
+ int rescue;
159
+ VALUE last_error;
160
+ VALUE next_recv;
161
+ int targetted;
162
+ struct FASTRUBYTHREADDATA* thread_data;
163
+ } frame;
164
+
165
+ frame.parent_frame = 0;
166
+ frame.rescue = 0;
167
+ frame.return_value = Qnil;
168
+ frame.thread_data = rb_current_thread_data();
169
+ frame.targetted = 0;
170
+
171
+ volatile VALUE block = Qfalse;
172
+
173
+ if (rb_block_given_p()) {
174
+ struct {
175
+ void* block_function_address;
176
+ void* block_function_param;
177
+ VALUE proc;
178
+ } block_struct;
179
+
180
+ block_struct.block_function_address = re_yield;
181
+ block_struct.block_function_param = 0;
182
+ block_struct.proc = rb_block_proc();
183
+
184
+ block = (VALUE)&block_struct;
185
+ }
154
186
 
155
- method_name[0] = '_';
156
- method_name[1] = 0;
157
187
 
158
- sprintf(method_name+1, \"#{method_name}\");
159
- sprintf(method_name+strlen(method_name), \"%li\", (long)NUM2PTR(rb_obj_id(CLASS_OF(self))));
160
-
161
- int i;
162
- for (i=0; i<argc_; i++) {
163
- sprintf(method_name+strlen(method_name), \"%li\", (long)NUM2PTR(rb_obj_id(CLASS_OF(argv[i]))));
164
- }
165
-
166
- void** address = 0;
167
- void* fptr = 0;
168
- ID id;
169
- VALUE rb_method_hash;
170
-
171
- id = rb_intern(method_name);
172
- rb_method_hash = rb_funcall(klass, #{intern_num :method_hash},1,#{literal_value method_name});
173
-
174
- if (rb_method_hash != Qnil) {
175
- VALUE tmp = rb_hash_aref(rb_method_hash, PTR2NUM(id));
176
- if (tmp != Qnil) {
177
- address = (void**)NUM2PTR(tmp);
178
- fptr = *address;
188
+ int aux = setjmp(frame.jmp);
189
+ if (aux != 0) {
190
+ if (aux == FASTRUBY_TAG_RAISE) {
191
+ rb_funcall(self, #{intern_num :raise}, 1, frame.thread_data->exception);
179
192
  }
180
- }
181
193
 
182
- if (fptr == 0) {
183
- VALUE argv_class[argc_+1];
184
-
185
- argv_class[0] = CLASS_OF(self);
186
- for (i=0; i<argc_; i++) {
187
- argv_class[i+1] = CLASS_OF(argv[i]);
188
- }
189
-
190
- VALUE signature = rb_ary_new4(argc_+1,argv_class);
191
-
192
- rb_funcall(#{global_klass_variable}, #{intern_num :build}, 2, signature,rb_str_new2(#{method_name.to_s.inspect}));
193
-
194
- id = rb_intern(method_name);
195
- rb_method_hash = rb_funcall(klass, #{intern_num :method_hash},1,#{literal_value method_name});
196
-
197
- if (rb_method_hash != Qnil) {
198
- VALUE tmp = rb_hash_aref(rb_method_hash, PTR2NUM(id));
199
- if (tmp != Qnil) {
200
- address = (void**)NUM2PTR(tmp);
201
- fptr = *address;
202
- }
203
- }
204
-
205
- if (fptr == 0) {
206
- rb_raise(rb_eRuntimeError, \"Error: method not found after build\");
194
+ if (frame.targetted == 0) {
195
+ frb_jump_tag(aux);
207
196
  }
208
197
 
198
+ return Qnil;
209
199
  }
210
-
211
- struct {
212
- void* parent_frame;
213
- void* plocals;
214
- jmp_buf jmp;
215
- VALUE return_value;
216
- int rescue;
217
- VALUE last_error;
218
- VALUE next_recv;
219
- int targetted;
220
- struct FASTRUBYTHREADDATA* thread_data;
221
- } frame;
222
-
223
- frame.parent_frame = 0;
224
- frame.rescue = 0;
225
- frame.return_value = Qnil;
226
- frame.thread_data = rb_current_thread_data();
227
- frame.targetted = 0;
228
-
229
- volatile VALUE block = Qfalse;
230
-
231
- if (rb_block_given_p()) {
232
- struct {
233
- void* block_function_address;
234
- void* block_function_param;
235
- VALUE proc;
236
- } block_struct;
237
-
238
- block_struct.block_function_address = re_yield;
239
- block_struct.block_function_param = 0;
240
- block_struct.proc = rb_block_proc();
241
-
242
- block = (VALUE)&block_struct;
243
- }
244
-
245
- int aux = setjmp(frame.jmp);
246
- if (aux != 0) {
247
- if (aux == FASTRUBY_TAG_RAISE) {
248
- rb_funcall(self, #{intern_num :raise}, 1, frame.thread_data->exception);
249
- }
250
-
251
- if (frame.targetted == 0) {
252
- frb_jump_tag(aux);
253
- }
254
-
255
- return Qnil;
256
- }
257
200
 
258
- VALUE tmp = Qnil;
259
- if (argv == 0) argv = &tmp;
201
+ VALUE tmp = Qnil;
202
+ if (argv == 0) argv = &tmp;
260
203
 
261
- return ((VALUE(*)(VALUE,VALUE,VALUE,int,VALUE*))fptr)(#{strmethodargs}, argc_, argv);
204
+ return #{dynamic_call(nilsignature, method_name.to_sym, false, false, global_klass_variable)}(self, (void*)block, (void*)&frame, argc_, argv);
262
205
  }"
263
206
  }
207
+
264
208
 
265
209
  end
266
210
  end
@@ -0,0 +1,211 @@
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(:defn, :method => :to_c_defn)
25
+ def to_c_defn(tree, result_var = nil)
26
+
27
+ method_name = tree[1]
28
+ args_tree = tree[2].select{|x| x.to_s[0] != ?&}
29
+
30
+ global_klass_variable = add_global_name("VALUE", "Qnil");
31
+
32
+ hash = Hash.new
33
+ value_cast = ( ["VALUE"]*(args_tree.size+2) ).join(",")
34
+
35
+ strmethodargs = "self,block,(VALUE)&frame"
36
+
37
+ anonymous_method_name = anonymous_dispatcher(global_klass_variable, method_name)
38
+ alt_options = options.dup
39
+
40
+ alt_options.delete(:self)
41
+ alt_options.delete(:main)
42
+
43
+ code = "
44
+
45
+
46
+ if (rb_obj_is_kind_of(#{locals_accessor}self, rb_cClass) || rb_obj_is_kind_of(#{locals_accessor}self, rb_cModule)) {
47
+
48
+ #{unless options[:fastruby_only]
49
+ "rb_define_method(plocals->self, #{method_name.to_s.inspect}, #{anonymous_method_name}, -1);"
50
+ end
51
+ }
52
+
53
+ #{global_klass_variable} = #{locals_accessor}self;
54
+ // set tree
55
+ rb_funcall(#{literal_value FastRuby}, #{intern_num :set_tree}, 4,
56
+ #{global_klass_variable},
57
+ rb_str_new2(#{method_name.to_s.inspect}),
58
+ #{literal_value tree},
59
+ #{literal_value alt_options}
60
+
61
+ );
62
+
63
+ } else {
64
+ VALUE obj = plocals->self;
65
+ rb_define_singleton_method(obj, #{method_name.to_s.inspect}, #{anonymous_method_name}, -1 );
66
+
67
+ #{global_klass_variable} = CLASS_OF(obj);
68
+ // set tree
69
+ rb_funcall(#{literal_value FastRuby}, #{intern_num :set_tree}, 4,
70
+ #{global_klass_variable},
71
+ rb_str_new2(#{method_name.to_s.inspect}),
72
+ #{literal_value tree},
73
+ #{literal_value alt_options}
74
+
75
+ );
76
+ }
77
+
78
+ "
79
+
80
+ if result_var
81
+ code + "\n#{result_var} = Qnil;"
82
+ else
83
+ inline_block code + "\nreturn Qnil;\n"
84
+ end
85
+ end
86
+
87
+ define_translator_for(:defs, :method => :to_c_defs)
88
+ def to_c_defs(tree, result_var = nil)
89
+ method_name = tree[2]
90
+ args_tree = tree[3].select{|x| x.to_s[0] != ?&}
91
+
92
+ global_klass_variable = add_global_name("VALUE", "Qnil");
93
+
94
+ hash = Hash.new
95
+ value_cast = ( ["VALUE"]*(args_tree.size+2) ).join(",")
96
+
97
+ strmethodargs = "self,block,(VALUE)&frame"
98
+
99
+ anonymous_method_name = anonymous_dispatcher(global_klass_variable, method_name)
100
+
101
+ alt_options = options.dup
102
+
103
+ alt_options.delete(:self)
104
+ alt_options.delete(:main)
105
+
106
+ code = "
107
+
108
+ VALUE obj = Qnil;
109
+ #{to_c tree[1], "obj"};
110
+ rb_define_singleton_method(obj, #{method_name.to_s.inspect}, #{anonymous_method_name}, -1 );
111
+
112
+ #{global_klass_variable} = CLASS_OF(obj);
113
+ // set tree
114
+ rb_funcall(#{literal_value FastRuby}, #{intern_num :set_tree}, 4,
115
+ #{global_klass_variable},
116
+ rb_str_new2(#{method_name.to_s.inspect}),
117
+ #{literal_value tree},
118
+ #{literal_value alt_options}
119
+
120
+ );
121
+
122
+ "
123
+
124
+ if result_var
125
+ code + "\n#{result_var} = Qnil;"
126
+ else
127
+ inline_block code + "\nreturn Qnil;\n"
128
+ end
129
+
130
+ end
131
+
132
+ define_translator_for(:scope, :method => :to_c_scope)
133
+ def to_c_scope(tree, result_var = nil)
134
+ if tree[1]
135
+ if result_var
136
+ to_c(tree[1], result_var)
137
+ else
138
+ to_c(tree[1])
139
+ end
140
+ else
141
+ "Qnil"
142
+ end
143
+ end
144
+
145
+ private
146
+
147
+ def anonymous_dispatcher(global_klass_variable, method_name)
148
+
149
+ strmethodargs = "self,block,(VALUE)&frame"
150
+ nilsignature = [nil]*32
151
+
152
+ anonymous_function{ |anonymous_method_name| "VALUE #{anonymous_method_name}(int argc_, VALUE* argv, VALUE self) {
153
+ struct {
154
+ void* parent_frame;
155
+ void* plocals;
156
+ jmp_buf jmp;
157
+ VALUE return_value;
158
+ int rescue;
159
+ VALUE last_error;
160
+ VALUE next_recv;
161
+ int targetted;
162
+ struct FASTRUBYTHREADDATA* thread_data;
163
+ } frame;
164
+
165
+ frame.parent_frame = 0;
166
+ frame.rescue = 0;
167
+ frame.return_value = Qnil;
168
+ frame.thread_data = rb_current_thread_data();
169
+ frame.targetted = 0;
170
+
171
+ volatile VALUE block = Qfalse;
172
+
173
+ if (rb_block_given_p()) {
174
+ struct {
175
+ void* block_function_address;
176
+ void* block_function_param;
177
+ VALUE proc;
178
+ } block_struct;
179
+
180
+ block_struct.block_function_address = re_yield;
181
+ block_struct.block_function_param = 0;
182
+ block_struct.proc = rb_block_proc();
183
+
184
+ block = (VALUE)&block_struct;
185
+ }
186
+
187
+
188
+ int aux = setjmp(frame.jmp);
189
+ if (aux != 0) {
190
+ if (aux == FASTRUBY_TAG_RAISE) {
191
+ rb_funcall(self, #{intern_num :raise}, 1, frame.thread_data->exception);
192
+ }
193
+
194
+ if (frame.targetted == 0) {
195
+ frb_jump_tag(aux);
196
+ }
197
+
198
+ return Qnil;
199
+ }
200
+
201
+ VALUE tmp = Qnil;
202
+ if (argv == 0) argv = &tmp;
203
+
204
+ return #{dynamic_call(nilsignature, method_name.to_sym, false, false, global_klass_variable)}(self, (void*)block, (void*)&frame, argc_, argv);
205
+ }"
206
+ }
207
+
208
+
209
+ end
210
+ end
211
+ end