fastruby 0.0.16 → 0.0.17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. data/CHANGELOG +17 -1
  2. data/Rakefile +1 -1
  3. data/ext/fastruby_base/fastruby_base.inl +81 -3
  4. data/lib/fastruby/fastruby_sexp.rb +21 -0
  5. data/lib/fastruby/getlocals.rb +2 -1
  6. data/lib/fastruby/object.rb +1 -1
  7. data/lib/fastruby/sexp_extension.rb +189 -0
  8. data/lib/fastruby/sexp_extension_edges.rb +210 -0
  9. data/lib/fastruby/translator/modules/block.rb +29 -22
  10. data/lib/fastruby/translator/modules/call.rb +211 -34
  11. data/lib/fastruby/translator/modules/defn.rb +64 -29
  12. data/lib/fastruby/translator/modules/exceptions.rb +1 -1
  13. data/lib/fastruby/translator/modules/flow.rb +93 -31
  14. data/lib/fastruby/translator/modules/iter.rb +277 -340
  15. data/lib/fastruby/translator/modules/literal.rb +97 -20
  16. data/lib/fastruby/translator/modules/logical.rb +40 -5
  17. data/lib/fastruby/translator/modules/method_group.rb +41 -19
  18. data/lib/fastruby/translator/modules/nonlocal.rb +74 -29
  19. data/lib/fastruby/translator/modules/variable.rb +151 -42
  20. data/lib/fastruby/translator/scope_mode_helper.rb +161 -0
  21. data/lib/fastruby/translator/translator.rb +389 -302
  22. data/lib/fastruby.rb +1 -1
  23. data/lib/fastruby.rb~ +36 -0
  24. data/spec/edges_helper.rb +91 -0
  25. data/spec/graph/base_spec.rb +35 -0
  26. data/spec/graph/path_spec.rb +48 -0
  27. data/spec/graph/vertex_spec.rb +58 -0
  28. data/spec/ruby/block/proc_as_block_spec.rb +214 -0
  29. data/spec/ruby/block/redo_spec.rb +133 -0
  30. data/spec/ruby/defn/single_function_spec.rb +50 -0
  31. data/spec/scope_mode/base_spec.rb +55 -0
  32. data/spec/scope_mode/block_spec.rb +105 -0
  33. data/spec/scope_mode/call_spec.rb +24 -0
  34. data/spec/scope_mode/exception_spec.rb +34 -0
  35. data/spec/scope_mode/flow_spec.rb +99 -0
  36. data/spec/scope_mode/optimization_spec.rb +130 -0
  37. data/spec/sexp2graph/base_spec.rb +36 -0
  38. data/spec/sexp2graph/exception_spec.rb +172 -0
  39. data/spec/sexp2graph/flow_spec.rb +67 -0
  40. data/spec/sexp2graph/logical_spec.rb +21 -0
  41. data/spec/sexp2graph/variable_spec.rb +26 -0
  42. metadata +110 -120
  43. data/lib/fastruby/self +0 -82
  44. data/lib/len +0 -280
  45. data/spec/block/proc_as_block_spec.rb +0 -111
  46. data/spec/block/redo_spec.rb +0 -67
  47. /data/spec/{base_spec.rb → ruby/base_spec.rb} +0 -0
  48. /data/spec/{block → ruby/block}/arguments_spec.rb +0 -0
  49. /data/spec/{block → ruby/block}/block_as_proc_spec.rb +0 -0
  50. /data/spec/{block → ruby/block}/break_spec.rb +0 -0
  51. /data/spec/{block → ruby/block}/callcc_spec.rb +0 -0
  52. /data/spec/{block → ruby/block}/lambda_spec.rb +0 -0
  53. /data/spec/{block → ruby/block}/next_spec.rb +0 -0
  54. /data/spec/{block → ruby/block}/proc_spec.rb +0 -0
  55. /data/spec/{block → ruby/block}/retry_spec.rb +0 -0
  56. /data/spec/{block_spec.rb → ruby/block_spec.rb} +0 -0
  57. /data/spec/{call → ruby/call}/base_call_spec.rb +0 -0
  58. /data/spec/{call → ruby/call}/multiple_args_spec.rb +0 -0
  59. /data/spec/{control_spec.rb → ruby/control_spec.rb} +0 -0
  60. /data/spec/{defn → ruby/defn}/default_args_spec.rb +0 -0
  61. /data/spec/{defn → ruby/defn}/multiple_args_spec.rb +0 -0
  62. /data/spec/{defn → ruby/defn}/replacement_spec.rb +0 -0
  63. /data/spec/{exception → ruby/exception}/base_spec.rb +0 -0
  64. /data/spec/{exception → ruby/exception}/ensure_spec.rb +0 -0
  65. /data/spec/{exception → ruby/exception}/exc_trap_spec.rb +0 -0
  66. /data/spec/{exception → ruby/exception}/internal_ex_spec.rb +0 -0
  67. /data/spec/{exception → ruby/exception}/syntaxis_spec.rb +0 -0
  68. /data/spec/{expression_spec.rb → ruby/expression_spec.rb} +0 -0
  69. /data/spec/{flow_control → ruby/flow_control}/case_spec.rb +0 -0
  70. /data/spec/{flow_control → ruby/flow_control}/for_spec.rb +0 -0
  71. /data/spec/{integrity_spec.rb → ruby/integrity_spec.rb} +0 -0
  72. /data/spec/{jump → ruby/jump}/next_spec.rb +0 -0
  73. /data/spec/{literal_spec.rb → ruby/literal_spec.rb} +0 -0
  74. /data/spec/{module_spec.rb → ruby/module_spec.rb} +0 -0
  75. /data/spec/{return_spec.rb → ruby/return_spec.rb} +0 -0
  76. /data/spec/{singleton_spec.rb → ruby/singleton_spec.rb} +0 -0
  77. /data/spec/{sugar_spec.rb → ruby/sugar_spec.rb} +0 -0
  78. /data/spec/{variable_spec.rb → ruby/variable_spec.rb} +0 -0
@@ -33,10 +33,10 @@ module FastRuby
33
33
  pframe = (void*)frame_param;
34
34
  plocals = (void*)pframe->plocals;
35
35
 
36
- if (FIX2LONG(plocals->block_function_address) == 0) {
36
+ if ((plocals->block_function_address) == 0) {
37
37
  #{_raise("rb_eLocalJumpError", "no block given")};
38
38
  } else {
39
- return ((VALUE(*)(int,VALUE*,VALUE,VALUE))FIX2LONG(plocals->block_function_address))(size, block_args, FIX2LONG(plocals->block_function_param), (VALUE)pframe);
39
+ return ((VALUE(*)(int,VALUE*,VALUE,VALUE))(plocals->block_function_address))(size, block_args, (VALUE)(plocals->block_function_param), (VALUE)pframe);
40
40
  }
41
41
  }
42
42
  "
@@ -45,15 +45,20 @@ module FastRuby
45
45
  splat_arg = tree.find{|x| x == :yield ? false : x[0] == :splat}
46
46
  ret = nil
47
47
  if splat_arg
48
- ret = inline_block "
49
- VALUE splat_array = #{to_c(splat_arg[1])};
48
+ ret = "
49
+ VALUE splat_array = Qnil;
50
+ VALUE block_aux = Qnil;
51
+ #{to_c(splat_arg[1], "splat_array")};
50
52
 
51
53
  if (CLASS_OF(splat_array) == rb_cArray) {
52
54
  VALUE block_args[_RARRAY_LEN(splat_array) + #{tree.size}];
53
55
  int i;
54
56
  #{
55
57
  (0..tree.size-3).map{|i|
56
- "block_args[#{i}] = #{to_c(tree[i+1])}"
58
+ "
59
+ #{to_c(tree[i+1], "block_aux")};
60
+ block_args[#{i}] = block_aux;
61
+ "
57
62
  }.join(";\n")
58
63
  };
59
64
 
@@ -61,53 +66,55 @@ module FastRuby
61
66
  block_args[i+#{tree.size-2}] = rb_ary_entry(splat_array,i);
62
67
  }
63
68
 
64
- return #{anonymous_function(&block_code)}((VALUE)pframe, block_args, _RARRAY_LEN(splat_array) + #{tree.size-2});
69
+ last_expression = #{anonymous_function(&block_code)}((VALUE)pframe, block_args, _RARRAY_LEN(splat_array) + #{tree.size-2});
65
70
  } else {
66
71
  VALUE block_args[1+#{tree.size}];
67
72
  #{
68
73
  (0..tree.size-3).map{|i|
69
- "block_args[#{i}] = #{to_c(tree[i+1])}"
74
+ "
75
+ #{to_c(tree[i+1], "block_aux")};
76
+ block_args[#{i}] = block_aux;
77
+ "
70
78
  }.join(";\n")
71
79
  };
72
80
 
73
81
  block_args[#{tree.size-2}] = splat_array;
74
- return #{anonymous_function(&block_code)}((VALUE)pframe, block_args, #{tree.size-1});
82
+ last_expression = #{anonymous_function(&block_code)}((VALUE)pframe, block_args, #{tree.size-1});
75
83
  }
76
84
 
77
85
  "
78
86
  else
79
87
  ret = if tree.size > 1
80
- anonymous_function(&block_code)+"((VALUE)pframe, (VALUE[]){#{tree[1..-1].map{|subtree| to_c subtree}.join(",")}},#{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})"
81
89
  else
82
- anonymous_function(&block_code)+"((VALUE)pframe, (VALUE[]){}, #{tree.size-1})"
90
+ "last_expression = " + anonymous_function(&block_code)+"((VALUE)pframe, (VALUE[]){}, #{tree.size-1})"
83
91
  end
84
92
  end
85
93
 
86
94
  protected_block(ret, false)
87
95
  end
88
96
 
89
- def to_c_block(tree)
97
+ def to_c_block(tree, result_variable = nil)
90
98
  if tree.size == 1
91
99
  return inline_block("return Qnil;")
92
100
  end
93
-
101
+
94
102
  str = ""
95
103
  str = tree[1..-2].map{ |subtree|
96
- to_c(subtree)
104
+ to_c(subtree,"last_expression")
97
105
  }.join(";")
98
106
 
99
107
  if tree[-1]
100
-
101
- if tree[-1][0] != :return
102
- str = str + ";last_expression = #{to_c(tree[-1])};"
103
- else
104
- str = str + ";#{to_c(tree[-1])};"
105
- end
108
+ str = str + ";#{to_c(tree[-1],"last_expression")};"
106
109
  end
107
110
 
108
- str << "return last_expression;"
109
-
110
- inline_block str
111
+ if result_variable
112
+ str << "#{result_variable} = last_expression;"
113
+ str
114
+ else
115
+ str << "return last_expression;"
116
+ inline_block str
117
+ end
111
118
  end
112
119
 
113
120
  end
@@ -23,12 +23,18 @@ module FastRuby
23
23
 
24
24
  register_translator_module self
25
25
 
26
- def to_c_call(tree, repass_var = nil)
26
+ def to_c_call(tree, result_var = nil)
27
27
  directive_code = directive(tree)
28
+ repass_var = @repass_var
29
+
28
30
  if directive_code
29
- return directive_code
31
+ if result_var
32
+ return "#{result_var} = #{directive_code};\n"
33
+ else
34
+ return directive_code
35
+ end
30
36
  end
31
-
37
+
32
38
  if tree[2] == :require
33
39
  tree[2] = :fastruby_require
34
40
  elsif tree[2] == :raise
@@ -36,10 +42,11 @@ module FastRuby
36
42
  args = tree[3]
37
43
  return _raise(args[1],args[2])
38
44
  end
39
-
45
+
40
46
  recv = tree[1]
41
47
  mname = tree[2]
42
48
  args = tree[3]
49
+ args_tree = tree[3]
43
50
 
44
51
  # search block_pass on arguments
45
52
  block_pass_arg = args.find{|arg| if arg == :arglist
@@ -47,24 +54,18 @@ module FastRuby
47
54
  else
48
55
  arg[0] == :block_pass
49
56
  end}
57
+
50
58
  if block_pass_arg
51
-
52
- call_tree = tree.dup
53
- call_tree[3] = args.select{|arg| if arg == :arglist
54
- true
55
- else
56
- arg[0] != :block_pass
57
- end
58
- }
59
-
60
- block_arguments_tree = s(:masgn, s(:array, s(:splat, s(:lasgn, :__xblock_arguments))))
61
- block_tree = s(:call, block_pass_arg[1], :call, s(:arglist, s(:splat, s(:lvar, :__xblock_arguments))))
62
-
63
- replace_iter_tree = s(:iter, call_tree, block_arguments_tree, block_tree).to_fastruby_sexp
64
-
65
- return to_c(replace_iter_tree)
59
+ args_tree = args_tree.dup.reject{|st|
60
+ if st.respond_to? :node_type
61
+ st.node_type == :block_pass
62
+ else
63
+ false
64
+ end
65
+ }
66
+ args = args_tree
66
67
  end
67
-
68
+
68
69
  mname = :require_fastruby if mname == :require
69
70
 
70
71
  argnum = args.size - 1
@@ -74,12 +75,40 @@ module FastRuby
74
75
  recvtype = infer_type(recv)
75
76
 
76
77
  if args.size > 1
78
+ if (not recvtype) or args.last[0] == :splat
79
+ if block_pass_arg
80
+ call_tree = tree.dup
81
+ call_tree[3] = args.select{|arg| if arg == :arglist
82
+ true
83
+ else
84
+ arg[0] != :block_pass
85
+ end
86
+ }
87
+
88
+ block_arguments_tree = s(:masgn, s(:array, s(:splat, s(:lasgn, :__xblock_arguments))))
89
+ block_tree = s(:call, s(:lvar, :__x_proc), :call, s(:arglist, s(:splat, s(:lvar, :__xblock_arguments))))
90
+
91
+ replace_iter_tree = s(:block,
92
+ s(:lasgn, :__x_proc, s(:call, block_pass_arg[1], :to_proc, s(:arglist))),
93
+ s(:iter, call_tree, block_arguments_tree, block_tree)
94
+ ).to_fastruby_sexp
95
+
96
+ if result_var
97
+ return to_c(replace_iter_tree,result_var)
98
+ else
99
+ return to_c(replace_iter_tree)
100
+ end
101
+ end
102
+ end
103
+
77
104
  if args.last[0] == :splat
78
- return protected_block(
79
- inline_block(
105
+ aux_varname = "_aux_" + rand(1000000).to_s
106
+ code = protected_block(
80
107
  "
81
108
 
82
- VALUE array = #{to_c args.last[1]};
109
+ VALUE array = Qnil;
110
+
111
+ #{to_c args.last[1], "array"};
83
112
 
84
113
  if (TYPE(array) != T_ARRAY) {
85
114
  array = rb_ary_new4(1,&array);
@@ -87,15 +116,21 @@ module FastRuby
87
116
 
88
117
  int argc = #{args.size-2};
89
118
  VALUE argv[#{args.size} + _RARRAY_LEN(array)];
90
-
119
+ VALUE #{aux_varname} = Qnil;
91
120
  #{
92
121
  i = -1
93
122
  args[1..-2].map {|arg|
94
123
  i = i + 1
95
- "argv[#{i}] = #{to_c arg}"
124
+ "#{to_c arg, aux_varname};
125
+ argv[#{i}] = #{aux_varname};
126
+ "
96
127
  }.join(";\n")
97
128
  };
98
129
 
130
+ VALUE recv = Qnil;
131
+
132
+ #{to_c recv, "recv"};
133
+
99
134
  int array_len = _RARRAY_LEN(array);
100
135
 
101
136
  int i;
@@ -104,14 +139,17 @@ module FastRuby
104
139
  argc++;
105
140
  }
106
141
 
107
- return rb_funcall2(#{to_c recv}, #{intern_num tree[2]}, argc, argv);
108
- "
109
- ), true, repass_var)
142
+ last_expression = rb_funcall2(recv, #{intern_num tree[2]}, argc, argv);
143
+ ", true, repass_var)
144
+
145
+ if result_var
146
+ return "#{result_var} = #{code};\n"
147
+ else
148
+ return code
149
+ end
110
150
  end
111
151
  end
112
152
 
113
- strargs = args[1..-1].map{|arg| to_c arg}.join(",")
114
-
115
153
  if recvtype
116
154
 
117
155
  address = nil
@@ -136,19 +174,158 @@ module FastRuby
136
174
  extraargs_signature = ""
137
175
  end
138
176
 
177
+ block_proc_tree = s(:call, block_pass_arg[1], :to_proc, s(:arglist)) if block_pass_arg
178
+
179
+ block_wrapping_proc = proc { |name| "
180
+ static VALUE #{name}(int argc, VALUE* argv, VALUE _locals, VALUE _parent_frame) {
181
+ return rb_proc_call(_locals, rb_ary_new4(argc, argv));
182
+ }
183
+ "
184
+ }
185
+
139
186
  if argnum == 0
140
187
  value_cast = "VALUE,VALUE,VALUE"
141
- "((VALUE(*)(#{value_cast}))#{encode_address(recvtype,signature,mname,tree,inference_complete)})(#{to_c recv}, Qfalse, (VALUE)pframe)"
188
+
189
+
190
+ if block_pass_arg or result_var
191
+ code = "
192
+ {
193
+ VALUE recv = Qnil;
194
+ #{to_c recv, "recv"};
195
+
196
+ #{@block_struct} block, *pblock = Qfalse;
197
+
198
+ #{if block_pass_arg
199
+ "
200
+ VALUE proc = Qnil;
201
+ #{to_c(block_proc_tree, "proc") }
202
+
203
+ VALUE block_address_value = rb_ivar_get(proc, #{intern_num "__block_address"});
204
+
205
+ if (block_address_value != Qnil) {
206
+ block.block_function_address = NUM2PTR(block_address_value);
207
+ block.block_function_param = NUM2PTR(rb_ivar_get(proc, #{intern_num "__block_param"}));
208
+ block.proc = proc;
209
+ pblock = &block;
210
+ } else {
211
+ // create a block from a proc
212
+ block.block_function_address = ((void*)#{anonymous_function(&block_wrapping_proc)});
213
+ block.block_function_param = (void*)proc;
214
+ block.proc = proc;
215
+ pblock = &block;
216
+ }
217
+
218
+ "
219
+ end
220
+ }
221
+
222
+ #{if result_var
223
+ "
224
+ #{result_var} = ((VALUE(*)(#{value_cast}))#{encode_address(recvtype,signature,mname,tree,inference_complete)})(recv, (VALUE)pblock, (VALUE)pframe);
225
+ "
226
+ else
227
+ "
228
+ ((VALUE(*)(#{value_cast}))#{encode_address(recvtype,signature,mname,tree,inference_complete)})(recv, (VALUE)pblock, (VALUE)pframe);
229
+ "
230
+ end
231
+ }
232
+ }
233
+ "
234
+
235
+ result_var ? code : inline_block(code)
236
+ else
237
+ "((VALUE(*)(#{value_cast}))#{encode_address(recvtype,signature,mname,tree,inference_complete)})(#{to_c recv}, Qfalse, (VALUE)pframe)"
238
+ end
239
+
142
240
  else
143
241
  value_cast = ( ["VALUE"]*(args.size) ).join(",") + ",VALUE,VALUE"
144
- "((VALUE(*)(#{value_cast}))#{encode_address(recvtype,signature,mname,tree,inference_complete)})(#{to_c recv}, Qfalse, (VALUE)pframe, #{strargs})"
242
+ suffix = "_" + rand(1000000).to_s+"_"
243
+
244
+ strargs = (0..args_tree.size-2).map{|i| "#{suffix}arg#{i}"}.join(",")
245
+ if block_pass_arg or result_var
246
+ code = "
247
+ {
248
+ VALUE recv = Qnil;
249
+
250
+ #{
251
+ (0..args_tree.size-2).map{ |x|
252
+ "VALUE #{suffix}arg#{x};"
253
+ }.join("\n")
254
+ }
255
+
256
+ #{
257
+ (0..args_tree.size-2).map{ |x|
258
+ to_c(args_tree[x+1], "#{suffix}arg#{x}") + ";"
259
+ }.join("\n")
260
+ }
261
+
262
+ #{to_c recv, "recv"};
263
+
264
+ #{@block_struct} block, *pblock = Qfalse;
265
+
266
+ #{if block_pass_arg
267
+ "
268
+ VALUE proc = Qnil;
269
+ #{to_c(block_proc_tree, "proc") }
270
+ VALUE block_address_value = rb_ivar_get(proc, #{intern_num "__block_address"});
271
+ if (block_address_value != Qnil) {
272
+ block.block_function_address = NUM2PTR(block_address_value);
273
+ block.block_function_param = NUM2PTR(rb_ivar_get(proc, #{intern_num "__block_param"}));
274
+ block.proc = proc;
275
+ pblock = &block;
276
+ } else {
277
+ // create a block from a proc
278
+ block.block_function_address = ((void*)#{anonymous_function(&block_wrapping_proc)});
279
+ block.block_function_param = (void*)proc;
280
+ block.proc = proc;
281
+ pblock = &block;
282
+ }
283
+
284
+ "
285
+ end
286
+ }
287
+
288
+ #{if result_var
289
+ "
290
+ #{result_var} = ((VALUE(*)(#{value_cast}))#{encode_address(recvtype,signature,mname,tree,inference_complete)})(recv, (VALUE)pblock, (VALUE)pframe, #{strargs});
291
+ "
292
+ else
293
+ "
294
+ ((VALUE(*)(#{value_cast}))#{encode_address(recvtype,signature,mname,tree,inference_complete)})(recv, (VALUE)pblock, (VALUE)pframe, #{strargs});
295
+ "
296
+ end
297
+ }
298
+
299
+
300
+ }
301
+ "
302
+ result_var ? code : inline_block(code)
303
+ else
304
+ strargs = args[1..-1].map{|arg| to_c arg}.join(",")
305
+ "((VALUE(*)(#{value_cast}))#{encode_address(recvtype,signature,mname,tree,inference_complete)})(#{to_c recv}, Qfalse, (VALUE)pframe, #{strargs})"
306
+ end
145
307
  end
146
308
 
147
309
  else # else recvtype
148
310
  if argnum == 0
149
- protected_block("rb_funcall(#{to_c recv}, #{intern_num tree[2]}, 0)", true, repass_var)
311
+ code = protected_block("last_expression = rb_funcall(#{to_c recv}, #{intern_num tree[2]}, 0)", true, repass_var)
312
+ if result_var
313
+ "
314
+ #{result_var} = #{code};
315
+ "
316
+ else
317
+ code
318
+ end
150
319
  else
151
- protected_block("rb_funcall(#{to_c recv}, #{intern_num tree[2]}, #{argnum}, #{strargs} )", true, repass_var)
320
+ strargs = args[1..-1].map{|arg| to_c arg}.join(",")
321
+ code = protected_block("last_expression = rb_funcall(#{to_c recv}, #{intern_num tree[2]}, #{argnum}, #{strargs} )", true, repass_var)
322
+ if result_var
323
+ "
324
+ #{result_var} = #{code};
325
+ "
326
+ else
327
+ code
328
+ end
152
329
  end
153
330
  end # if recvtype
154
331
  end
@@ -22,7 +22,7 @@ module FastRuby
22
22
  module DefnTranslator
23
23
  register_translator_module self
24
24
 
25
- def to_c_defn(tree)
25
+ def to_c_defn(tree, result_var = nil)
26
26
 
27
27
  method_name = tree[1]
28
28
  args_tree = tree[2].select{|x| x.to_s[0] != ?&}
@@ -40,27 +40,49 @@ module FastRuby
40
40
  alt_options.delete(:self)
41
41
  alt_options.delete(:main)
42
42
 
43
- inline_block "
43
+ code = "
44
44
 
45
- usleep(0);
46
- rb_define_method(plocals->self, #{method_name.to_s.inspect}, #{anonymous_method_name}, -1);
45
+
46
+ if (rb_obj_is_kind_of(plocals->self, rb_cClass) || rb_obj_is_kind_of(plocals->self, rb_cModule)) {
47
+ rb_define_method(plocals->self, #{method_name.to_s.inspect}, #{anonymous_method_name}, -1);
48
+
49
+ #{global_klass_variable} = plocals->self;
50
+ // set tree
51
+ rb_funcall(#{literal_value FastRuby}, #{intern_num :set_tree}, 5,
52
+ #{global_klass_variable},
53
+ rb_str_new2(#{method_name.to_s.inspect}),
54
+ #{literal_value tree},
55
+ #{literal_value snippet_hash},
56
+ #{literal_value alt_options}
57
+
58
+ );
59
+
60
+ } else {
61
+ VALUE obj = plocals->self;
62
+ rb_define_singleton_method(obj, #{method_name.to_s.inspect}, #{anonymous_method_name}, -1 );
63
+
64
+ #{global_klass_variable} = CLASS_OF(obj);
65
+ // set tree
66
+ rb_funcall(#{literal_value FastRuby}, #{intern_num :set_tree}, 5,
67
+ #{global_klass_variable},
68
+ rb_str_new2(#{method_name.to_s.inspect}),
69
+ #{literal_value tree},
70
+ #{literal_value snippet_hash},
71
+ #{literal_value alt_options}
72
+
73
+ );
74
+ }
47
75
 
48
- #{global_klass_variable} = plocals->self;
49
- // set tree
50
- rb_funcall(#{literal_value FastRuby}, #{intern_num :set_tree}, 5,
51
- #{global_klass_variable},
52
- rb_str_new2(#{method_name.to_s.inspect}),
53
- #{literal_value tree},
54
- #{literal_value snippet_hash},
55
- #{literal_value alt_options}
56
-
57
- );
58
-
59
76
  "
60
77
 
78
+ if result_var
79
+ code + "\n#{result_var} = Qnil;"
80
+ else
81
+ inline_block code + "\nreturn Qnil;\n"
82
+ end
61
83
  end
62
84
 
63
- def to_c_defs(tree)
85
+ def to_c_defs(tree, result_var = nil)
64
86
  method_name = tree[2]
65
87
  args_tree = tree[3].select{|x| x.to_s[0] != ?&}
66
88
 
@@ -78,9 +100,10 @@ module FastRuby
78
100
  alt_options.delete(:self)
79
101
  alt_options.delete(:main)
80
102
 
81
- inline_block "
103
+ code = "
82
104
 
83
- VALUE obj = #{to_c tree[1]};
105
+ VALUE obj = Qnil;
106
+ #{to_c tree[1], "obj"};
84
107
  rb_define_singleton_method(obj, #{method_name.to_s.inspect}, #{anonymous_method_name}, -1 );
85
108
 
86
109
  #{global_klass_variable} = CLASS_OF(obj);
@@ -95,12 +118,22 @@ module FastRuby
95
118
  );
96
119
 
97
120
  "
121
+
122
+ if result_var
123
+ code + "\n#{result_var} = Qnil;"
124
+ else
125
+ inline_block code + "\nreturn Qnil;\n"
126
+ end
98
127
 
99
128
  end
100
129
 
101
- def to_c_scope(tree)
130
+ def to_c_scope(tree, result_var = nil)
102
131
  if tree[1]
103
- to_c(tree[1])
132
+ if result_var
133
+ to_c(tree[1], result_var)
134
+ else
135
+ to_c(tree[1])
136
+ end
104
137
  else
105
138
  "Qnil"
106
139
  end
@@ -120,11 +153,11 @@ private
120
153
  method_name[1] = 0;
121
154
 
122
155
  sprintf(method_name+1, \"#{method_name}\");
123
- sprintf(method_name+strlen(method_name), \"%lu\", FIX2LONG(rb_obj_id(CLASS_OF(self))));
156
+ sprintf(method_name+strlen(method_name), \"%lu\", (unsigned long)NUM2PTR(rb_obj_id(CLASS_OF(self))));
124
157
 
125
158
  int i;
126
159
  for (i=0; i<argc_; i++) {
127
- sprintf(method_name+strlen(method_name), \"%lu\", FIX2LONG(rb_obj_id(CLASS_OF(argv[i]))));
160
+ sprintf(method_name+strlen(method_name), \"%lu\", (unsigned long)NUM2PTR(rb_obj_id(CLASS_OF(argv[i]))));
128
161
  }
129
162
 
130
163
  void** address = 0;
@@ -136,9 +169,9 @@ private
136
169
  rb_method_hash = rb_funcall(klass, #{intern_num :method_hash},1,#{literal_value method_name});
137
170
 
138
171
  if (rb_method_hash != Qnil) {
139
- VALUE tmp = rb_hash_aref(rb_method_hash, LONG2FIX(id));
172
+ VALUE tmp = rb_hash_aref(rb_method_hash, PTR2NUM(id));
140
173
  if (tmp != Qnil) {
141
- address = (void**)FIX2LONG(tmp);
174
+ address = (void**)NUM2PTR(tmp);
142
175
  fptr = *address;
143
176
  }
144
177
  }
@@ -159,9 +192,9 @@ private
159
192
  rb_method_hash = rb_funcall(klass, #{intern_num :method_hash},1,#{literal_value method_name});
160
193
 
161
194
  if (rb_method_hash != Qnil) {
162
- VALUE tmp = rb_hash_aref(rb_method_hash, LONG2FIX(id));
195
+ VALUE tmp = rb_hash_aref(rb_method_hash, PTR2NUM(id));
163
196
  if (tmp != Qnil) {
164
- address = (void**)FIX2LONG(tmp);
197
+ address = (void**)NUM2PTR(tmp);
165
198
  fptr = *address;
166
199
  }
167
200
  }
@@ -190,16 +223,18 @@ private
190
223
  frame.thread_data = rb_current_thread_data();
191
224
  frame.targetted = 0;
192
225
 
193
- VALUE block = Qfalse;
226
+ volatile VALUE block = Qfalse;
194
227
 
195
228
  if (rb_block_given_p()) {
196
229
  struct {
197
- void *block_function_address;
198
- void *block_function_param;
230
+ void* block_function_address;
231
+ void* block_function_param;
232
+ VALUE proc;
199
233
  } block_struct;
200
234
 
201
235
  block_struct.block_function_address = re_yield;
202
236
  block_struct.block_function_param = 0;
237
+ block_struct.proc = rb_block_proc();
203
238
 
204
239
  block = (VALUE)&block_struct;
205
240
  }
@@ -86,7 +86,7 @@ module FastRuby
86
86
  end
87
87
 
88
88
  frame_call(
89
- frame(to_c(tree[1])+";","
89
+ "ret = " + frame(to_c(tree[1])+";","
90
90
  #{rescue_code}
91
91
  ", else_tree ? to_c(else_tree) : nil, 1)
92
92