fastruby 0.0.16 → 0.0.17

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