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
@@ -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