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
@@ -23,7 +23,7 @@ module FastRuby
23
23
 
24
24
  register_translator_module IterTranslator
25
25
 
26
- def to_c_iter(tree)
26
+ def to_c_iter(tree, result_var = nil)
27
27
 
28
28
  call_tree = tree[1]
29
29
  args_tree = tree[2]
@@ -31,7 +31,11 @@ module FastRuby
31
31
 
32
32
  directive_code = directive(call_tree)
33
33
  if directive_code
34
- return directive_code
34
+ if result_var
35
+ return "#{result_var} = #{directive_code};\n"
36
+ else
37
+ return directive_code
38
+ end
35
39
  end
36
40
 
37
41
  other_call_tree = call_tree.dup
@@ -75,31 +79,9 @@ module FastRuby
75
79
  str_arg_initialization = ""
76
80
 
77
81
  str_impl = ""
78
-
79
- on_block do
80
- # if impl_tree is a block, implement the last node with a return
81
- if anonymous_impl
82
- if anonymous_impl[0] == :block
83
- str_impl = anonymous_impl[1..-2].map{ |subtree|
84
- to_c(subtree)
85
- }.join(";")
86
-
87
- if anonymous_impl[-1][0] != :return and anonymous_impl[-1][0] != :break and anonymous_impl[-1][0] != :next
88
- str_impl = str_impl + ";last_expression = (#{to_c(anonymous_impl[-1])});"
89
- else
90
- str_impl = str_impl + ";#{to_c(anonymous_impl[-1])};"
91
- end
92
- else
93
- if anonymous_impl[0] != :return and anonymous_impl[0] != :break and anonymous_impl[0] != :next
94
- str_impl = str_impl + ";last_expression = (#{to_c(anonymous_impl)});"
95
- else
96
- str_impl = str_impl + ";#{to_c(anonymous_impl)};"
97
- end
98
- end
99
- else
100
- str_impl = "last_expression = Qnil;"
101
- end
102
- end
82
+ on_block do
83
+ str_impl = to_c(anonymous_impl, "last_expression")
84
+ end
103
85
 
104
86
  if not args_tree
105
87
  elsif args_tree.first == :lasgn
@@ -154,21 +136,70 @@ module FastRuby
154
136
  end
155
137
  end
156
138
  end
157
- rb_funcall_caller_code = nil
139
+ str_recv = "pframe->next_recv"
140
+ str_recv = "plocals->self" unless recv_tree
158
141
 
159
- if call_args_tree.size > 1
142
+ strargs = if call_args_tree.size > 1
143
+ "," + (0..call_args_tree.size-2).map{|i| "arg#{i}"}.join(",")
144
+ else
145
+ ""
146
+ end
147
+
148
+ str_evaluate_args = ""
160
149
 
161
- str_recv = "pframe->next_recv"
150
+ rb_funcall_caller_code = proc { |name, call_type| "
151
+ static VALUE #{name}(VALUE param) {
152
+ // call to #{call_tree[2]}
153
+ VALUE last_expression = Qnil;
154
+
155
+ #{str_lvar_initialization}
156
+ #{str_evaluate_args};
157
+
158
+ VALUE ret = rb_funcall(#{str_recv}, #{intern_num call_tree[2]}, #{call_args_tree.size-1} #{strargs});
159
+ #{
160
+ if call_type == :lambda
161
+ "
162
162
 
163
- str_recv = "plocals->self" unless recv_tree
163
+ // freeze all stacks
164
+ struct FASTRUBYTHREADDATA* thread_data = rb_current_thread_data();
165
+
166
+ if (thread_data != 0) {
167
+ VALUE rb_stack_chunk = thread_data->rb_stack_chunk;
168
+
169
+ // add reference to stack chunk to lambda object
170
+ rb_ivar_set(ret,#{intern_num :_fastruby_stack_chunk},rb_stack_chunk);
171
+
172
+ // freeze the complete chain of stack chunks
173
+ while (rb_stack_chunk != Qnil) {
174
+ struct STACKCHUNK* stack_chunk;
175
+ Data_Get_Struct(rb_stack_chunk,struct STACKCHUNK,stack_chunk);
176
+
177
+ stack_chunk_freeze(stack_chunk);
178
+
179
+ rb_stack_chunk = rb_ivar_get(rb_stack_chunk,#{intern_num :_parent_stack_chunk});
180
+ }
181
+ }
182
+ "
183
+ end
184
+ }
185
+ return ret;
186
+ }
187
+ "
188
+ }
189
+
190
+
191
+ if call_args_tree.size > 1
164
192
  if call_args_tree.last[0] == :splat
165
- rb_funcall_caller_code = proc { |name| "
193
+ rb_funcall_caller_code = proc { |name,call_type| "
166
194
  static VALUE #{name}(VALUE param) {
167
195
  // call to #{call_tree[2]}
168
196
 
197
+ VALUE last_expression = Qnil;
169
198
  #{str_lvar_initialization}
170
199
 
171
- VALUE array = #{to_c call_args_tree.last[1]};
200
+ VALUE array = Qnil;
201
+
202
+ #{to_c call_args_tree.last[1], "array"};
172
203
 
173
204
  if (TYPE(array) != T_ARRAY) {
174
205
  array = rb_ary_new4(1,&array);
@@ -177,11 +208,15 @@ module FastRuby
177
208
  int argc = #{call_args_tree.size-2};
178
209
  VALUE argv[#{call_args_tree.size} + _RARRAY_LEN(array)];
179
210
 
211
+ VALUE aux_ = Qnil;;
180
212
  #{
181
213
  i = -1
182
214
  call_args_tree[1..-2].map {|arg|
183
215
  i = i + 1
184
- "argv[#{i}] = #{to_c arg}"
216
+ "
217
+ #{to_c arg, "aux_"};
218
+ argv[#{i}] = aux_;
219
+ "
185
220
  }.join(";\n")
186
221
  };
187
222
 
@@ -196,67 +231,24 @@ module FastRuby
196
231
  return rb_funcall2(#{str_recv}, #{intern_num call_tree[2]}, argc, argv);
197
232
  }
198
233
  "
199
- }
234
+ }
200
235
  else
201
- str_called_code_args = call_args_tree[1..-1].map{ |subtree| to_c subtree }.join(",")
202
- rb_funcall_caller_code = proc { |name| "
203
- static VALUE #{name}(VALUE param) {
204
- // call to #{call_tree[2]}
205
-
206
- #{str_lvar_initialization}
207
- return rb_funcall(#{str_recv}, #{intern_num call_tree[2]}, #{call_args_tree.size-1}, #{str_called_code_args});
208
- }
236
+ str_evaluate_args = "
237
+ #{
238
+ (0..call_args_tree.size-2).map{|i|
239
+ "VALUE arg#{i} = Qnil;"
240
+ }.join("\n")
241
+ }
242
+
243
+ #{
244
+ (0..call_args_tree.size-2).map{|i|
245
+ to_c(call_args_tree[i+1], "arg#{i}")+";"
246
+ }.join("\n")
247
+ }
209
248
  "
210
- }
211
249
  end
212
-
213
- rb_funcall_caller_code_with_lambda = rb_funcall_caller_code
214
- else
215
- str_recv = "pframe->next_recv"
216
- str_recv = "plocals->self" unless recv_tree
217
-
218
- rb_funcall_caller_code = proc { |name| "
219
- static VALUE #{name}(VALUE param) {
220
- // call to #{call_tree[2]}
221
- #{str_lvar_initialization}
222
- return rb_funcall(#{str_recv}, #{intern_num call_tree[2]}, 0);
223
- }
224
- "
225
- }
226
-
227
- rb_funcall_caller_code_with_lambda = proc { |name| "
228
- static VALUE #{name}(VALUE param) {
229
- // call to #{call_tree[2]}
230
- #{str_lvar_initialization}
231
- VALUE ret = rb_funcall(#{str_recv}, #{intern_num call_tree[2]}, 0);
232
-
233
- // freeze all stacks
234
- struct FASTRUBYTHREADDATA* thread_data = rb_current_thread_data();
235
-
236
- if (thread_data != 0) {
237
- VALUE rb_stack_chunk = thread_data->rb_stack_chunk;
238
-
239
- // add reference to stack chunk to lambda object
240
- rb_ivar_set(ret,#{intern_num :_fastruby_stack_chunk},rb_stack_chunk);
241
-
242
- // freeze the complete chain of stack chunks
243
- while (rb_stack_chunk != Qnil) {
244
- struct STACKCHUNK* stack_chunk;
245
- Data_Get_Struct(rb_stack_chunk,struct STACKCHUNK,stack_chunk);
246
-
247
- stack_chunk_freeze(stack_chunk);
248
-
249
- rb_stack_chunk = rb_ivar_get(rb_stack_chunk,#{intern_num :_parent_stack_chunk});
250
- }
251
- }
252
-
253
- return ret;
254
- }
255
- "
256
- }
250
+ end
257
251
 
258
- end
259
-
260
252
  argument_array_read = "
261
253
  VALUE arg;
262
254
  #{
@@ -279,17 +271,16 @@ module FastRuby
279
271
  }
280
272
  "
281
273
 
282
-
283
- rb_funcall_block_code_with_lambda = proc { |name| "
274
+ rb_funcall_block_code = proc { |name,call_type| "
284
275
  static VALUE #{name}(VALUE arg_, VALUE _plocals, int argc, VALUE* argv) {
285
276
  // block for call to #{call_tree[2]}
286
277
  #{argument_array_read}
287
-
288
- VALUE last_expression = Qnil;
278
+
279
+ volatile VALUE last_expression = Qnil;
289
280
 
290
281
  #{@frame_struct} frame;
291
- #{@frame_struct} *pframe = (void*)&frame;
292
- #{@locals_struct} *plocals = (void*)_plocals;
282
+ #{@frame_struct} * volatile pframe = (void*)&frame;
283
+ #{@locals_struct} * volatile plocals = (void*)_plocals;
293
284
 
294
285
  frame.plocals = plocals;
295
286
  frame.parent_frame = 0;
@@ -298,80 +289,50 @@ module FastRuby
298
289
  frame.targetted = 0;
299
290
  frame.thread_data = rb_current_thread_data();
300
291
 
301
- // create a fake parent frame representing the lambda method frame and a fake locals scope
302
- VALUE old_call_frame = ((typeof(plocals))(pframe->plocals))->call_frame;
303
- ((typeof(plocals))(pframe->plocals))->call_frame = LONG2FIX(pframe);
292
+ #{str_arg_initialization}
304
293
 
305
- int aux = setjmp(frame.jmp);
306
- if (aux != 0) {
307
- if (aux == FASTRUBY_TAG_BREAK) {
308
- return frame.return_value;
309
- } else if (aux == FASTRUBY_TAG_NEXT) {
310
- return pframe->thread_data->accumulator;
294
+ #{
295
+ if call_type == :lambda or call_type == :proc_new
296
+ "
297
+ void* volatile old_call_frame = ((typeof(plocals))(pframe->plocals))->call_frame;
298
+ ((typeof(plocals))(pframe->plocals))->call_frame = pframe;
299
+ "
300
+ end
301
+ }
302
+
303
+ int aux = setjmp(frame.jmp);
304
+ if (aux != 0) {
305
+
306
+ if (aux == FASTRUBY_TAG_NEXT) {
307
+ last_expression = pframe->thread_data->accumulator;
308
+ goto fastruby_local_next;
311
309
  } else if (aux == FASTRUBY_TAG_REDO) {
312
310
  // do nothing and let execute the block again
311
+ #{
312
+ if call_type == :lambda
313
+ "
314
+
315
+ } else if (aux == FASTRUBY_TAG_BREAK) {
316
+ last_expression = frame.return_value;
317
+ goto fastruby_local_next;
318
+ "
319
+ end
320
+ }
321
+ #{
322
+ if call_type == :lambda or call_type == :proc_new
323
+ "
313
324
  } else if (aux == FASTRUBY_TAG_RAISE) {
314
325
  rb_funcall(((typeof(plocals))(pframe->plocals))->self, #{intern_num :raise}, 1, frame.thread_data->exception);
315
326
  return Qnil;
327
+ "
328
+ end
329
+ }
316
330
  } else {
317
- if (aux == FASTRUBY_TAG_RETURN) {
318
- if (plocals->targetted == 1) {
319
- ((typeof(plocals))(pframe->plocals))->call_frame = old_call_frame;
320
- return ((typeof(plocals))(pframe->plocals))->return_value;
321
- } else {
322
- rb_raise(rb_eLocalJumpError, \"unexpected return\");
323
- }
324
- } else {
325
- rb_raise(rb_eLocalJumpError, \"unexpected return\");
326
- }
327
-
328
- ((typeof(plocals))(pframe->plocals))->call_frame = old_call_frame;
329
- return frame.return_value;
330
-
331
- }
332
- }
333
-
334
- #{str_arg_initialization}
335
- #{str_impl}
336
-
337
- ((typeof(plocals))(pframe->plocals))->call_frame = old_call_frame;
338
- return last_expression;
339
- }
340
- "
341
- }
342
-
343
- rb_funcall_block_code_proc_new = proc { |name| "
344
- static VALUE #{name}(VALUE arg_, VALUE _plocals, int argc, VALUE* argv) {
345
- // block for call to #{call_tree[2]}
346
- #{argument_array_read}
347
-
348
- VALUE last_expression = Qnil;
349
-
350
- #{@frame_struct} frame;
351
- #{@frame_struct} *pframe = (void*)&frame;
352
- #{@locals_struct} *plocals = (void*)_plocals;
353
-
354
- frame.plocals = plocals;
355
- frame.parent_frame = 0;
356
- frame.return_value = Qnil;
357
- frame.rescue = 0;
358
- frame.targetted = 0;
359
- frame.thread_data = rb_current_thread_data();
360
-
361
- // create a fake parent frame representing the lambda method frame and a fake locals scope
362
- VALUE old_call_frame = ((typeof(plocals))(pframe->plocals))->call_frame;
363
- ((typeof(plocals))(pframe->plocals))->call_frame = LONG2FIX(pframe);
364
-
365
- int aux = setjmp(frame.jmp);
366
- if (aux != 0) {
367
- if (aux == FASTRUBY_TAG_NEXT) {
368
- return pframe->thread_data->accumulator;
369
- } else if (aux == FASTRUBY_TAG_REDO) {
370
- // do nothing and let execute the block again
371
- } else if (aux == FASTRUBY_TAG_RAISE) {
372
- rb_funcall(((typeof(plocals))(pframe->plocals))->self, #{intern_num :raise}, 1, frame.thread_data->exception);
373
- return Qnil;
374
- } else {
331
+ #{
332
+ case call_type
333
+ when :proc_new
334
+ "
335
+ _local_return:
375
336
  if (plocals->targetted == 1) {
376
337
  if (plocals->active == Qfalse) {
377
338
  rb_raise(rb_eLocalJumpError,\"return from proc-closure\");
@@ -382,110 +343,86 @@ module FastRuby
382
343
  } else {
383
344
  rb_raise(rb_eLocalJumpError, \"unexpected return\");
384
345
  }
385
- }
386
- }
387
-
388
- #{str_arg_initialization}
389
- #{str_impl}
390
-
391
- ((typeof(plocals))(pframe->plocals))->call_frame = old_call_frame;
392
-
393
- return last_expression;
394
- }
395
- "
396
- }
397
-
398
-
399
- rb_funcall_block_code = proc { |name| "
400
- static VALUE #{name}(VALUE arg_, VALUE _plocals, int argc, VALUE* argv) {
401
- // block for call to #{call_tree[2]}
402
- #{argument_array_read}
403
-
404
- VALUE last_expression = Qnil;
405
-
406
- #{@frame_struct} frame;
407
- #{@frame_struct} *pframe = (void*)&frame;
408
- #{@locals_struct} *plocals = (void*)_plocals;
409
-
410
- frame.plocals = plocals;
411
- frame.parent_frame = 0;
412
- frame.return_value = Qnil;
413
- frame.rescue = 0;
414
- frame.targetted = 0;
415
- frame.thread_data = rb_current_thread_data();
416
-
417
- int aux = setjmp(frame.jmp);
418
- if (aux != 0) {
346
+ "
347
+ when :lambda
348
+ "
349
+ if (aux == FASTRUBY_TAG_RETURN) {
350
+ if (plocals->targetted == 1) {
351
+ last_expression = ((typeof(plocals))(pframe->plocals))->return_value;
352
+ goto fastruby_local_next;
419
353
 
420
- if (aux == FASTRUBY_TAG_NEXT) {
421
- return pframe->thread_data->accumulator;
422
- } else if (aux == FASTRUBY_TAG_REDO) {
423
- // do nothing and let execute the block again
424
- } else {
354
+ } else {
355
+ rb_raise(rb_eLocalJumpError, \"unexpected return\");
356
+ }
357
+ } else {
358
+ rb_raise(rb_eLocalJumpError, \"unexpected return\");
359
+ }
360
+ "
361
+ else
362
+ "
425
363
  frb_jump_tag(aux);
426
364
  return frame.return_value;
427
- }
428
- }
429
-
430
-
431
- #{str_arg_initialization}
432
- #{str_impl}
433
-
434
- return last_expression;
435
- }
436
- "
437
- }
438
-
439
- rb_funcall_block_code_callcc = proc { |name| "
440
- static VALUE #{name}(VALUE arg, VALUE _plocals, int argc, VALUE* argv) {
441
- #{
442
- # TODO: access directly to argc and argv for optimal execution
443
- if RUBY_VERSION =~ /^1\.9/
444
- "arg = rb_ary_new4(argc,argv);"
445
- end
446
- }
447
-
448
- // block for call to #{call_tree[2]}
449
- VALUE last_expression = Qnil;
450
-
451
- #{@frame_struct} frame;
452
- #{@frame_struct} *pframe = (void*)&frame;
453
- #{@locals_struct} *plocals = (void*)_plocals;
454
-
455
- frame.plocals = plocals;
456
- frame.parent_frame = 0;
457
- frame.return_value = Qnil;
458
- frame.rescue = 0;
459
- frame.targetted = 0;
460
- frame.thread_data = rb_current_thread_data();
461
-
462
- int aux = setjmp(frame.jmp);
463
- if (aux != 0) {
365
+ "
366
+ end
367
+ }
464
368
 
465
- if (aux == FASTRUBY_TAG_NEXT) {
466
- return pframe->thread_data->accumulator;
467
- } else if (aux == FASTRUBY_TAG_REDO) {
468
- // do nothing and let execute the block again
469
- } else {
470
- frb_jump_tag(aux);
471
- return frame.return_value;
472
369
  }
473
370
  }
474
-
371
+
372
+ #{
373
+ if call_type == :callcc
374
+ "
475
375
  if (rb_obj_is_kind_of(arg, rb_const_get(rb_cObject, #{intern_num :Continuation}))) {
476
376
  struct FASTRUBYTHREADDATA* thread_data = frame.thread_data;
477
377
  rb_ivar_set(arg,#{intern_num :__stack_chunk},thread_data->rb_stack_chunk);
478
378
  }
379
+ "
380
+ end
381
+ }
479
382
 
480
- #{str_arg_initialization}
481
- #{str_impl}
383
+ fastruby_local_redo:
384
+ #{str_impl};
482
385
 
386
+ #{
387
+ case call_type
388
+ when :proc_new
389
+ "
483
390
  return last_expression;
484
- }
391
+ local_return:
392
+ aux = FASTRUBY_TAG_RETURN;
393
+ plocals->return_value = last_expression;
394
+ plocals->targetted = 1;
395
+ goto _local_return;
396
+ "
397
+ when :lambda
398
+ "
399
+ local_return:
400
+ "
401
+ else
402
+ "
403
+ return last_expression;
404
+ local_return:
405
+ plocals->return_value = last_expression;
406
+ plocals->targetted = 1;
407
+ frb_jump_tag(FASTRUBY_TAG_RETURN);
408
+ "
409
+ end
410
+ }
411
+
412
+
413
+ fastruby_local_next:
414
+ #{
415
+ if call_type == :proc_new or call_type == :lambda
416
+ "
417
+ ((typeof(plocals))(pframe->plocals))->call_frame = old_call_frame;
418
+ "
419
+ end
420
+ }
421
+ return last_expression;
422
+ }
485
423
  "
486
424
  }
487
425
 
488
-
489
426
  fastruby_str_arg_initialization = ""
490
427
 
491
428
  if not args_tree
@@ -515,11 +452,11 @@ module FastRuby
515
452
  block_code = proc { |name| "
516
453
  static VALUE #{name}(int argc, VALUE* argv, VALUE _locals, VALUE _parent_frame) {
517
454
  // block for call to #{call_tree[2]}
518
- VALUE last_expression = Qnil;
455
+ volatile VALUE last_expression = Qnil;
519
456
  #{@frame_struct} frame;
520
- #{@frame_struct} *pframe = (void*)&frame;
521
- #{@frame_struct} *parent_frame = (void*)_parent_frame;
522
- #{@locals_struct} *plocals;
457
+ #{@frame_struct} * volatile pframe = (void*)&frame;
458
+ #{@frame_struct} * volatile parent_frame = (void*)_parent_frame;
459
+ #{@locals_struct} * volatile plocals;
523
460
 
524
461
  frame.plocals = (void*)_locals;
525
462
  frame.parent_frame = parent_frame;
@@ -531,6 +468,8 @@ module FastRuby
531
468
 
532
469
  plocals = frame.plocals;
533
470
 
471
+ #{fastruby_str_arg_initialization}
472
+
534
473
  int aux = setjmp(frame.jmp);
535
474
  if (aux != 0) {
536
475
  if (pframe->targetted == 0) {
@@ -545,63 +484,35 @@ module FastRuby
545
484
 
546
485
  }
547
486
 
548
- #{fastruby_str_arg_initialization}
549
- #{str_impl}
487
+ fastruby_local_redo:
488
+ #{str_impl};
550
489
 
551
490
  return last_expression;
552
- }
491
+ local_return:
492
+ plocals->return_value = last_expression;
493
+ plocals->targetted = 1;
494
+ longjmp(pframe->jmp, FASTRUBY_TAG_RETURN);
495
+ fastruby_local_next:
496
+ return last_expression; }
553
497
  "
554
498
  }
555
499
 
556
- str_recv = "plocals->self"
557
-
558
- if recv_tree
559
- str_recv = to_c recv_tree
560
- end
561
-
562
500
  caller_code = nil
563
501
  convention_global_name = add_global_name("int",0)
564
-
565
- call_frame_struct_code = "
566
- #{@block_struct} block;
567
-
568
- block.block_function_address = (void*)#{anonymous_function(&block_code)};
569
- block.block_function_param = (void*)plocals;
570
-
571
- // create a call_frame
572
- #{@frame_struct} call_frame;
573
-
574
- call_frame.parent_frame = (void*)pframe;
575
- call_frame.plocals = plocals;
576
- call_frame.return_value = Qnil;
577
- call_frame.targetted = 0;
578
- call_frame.thread_data = rb_current_thread_data();
579
-
580
- VALUE old_call_frame = plocals->call_frame;
581
- plocals->call_frame = LONG2FIX(&call_frame);
582
-
583
- int aux = setjmp(call_frame.jmp);
584
- if (aux != 0) {
585
- #{@frame_struct}* pframe_ = (void*)pframe;
586
-
587
- if (aux == FASTRUBY_TAG_RETRY ) {
588
- // do nothing and let the call execute again
589
- } else {
590
- if (call_frame.targetted == 0) {
591
- longjmp(pframe_->jmp,aux);
592
- }
593
-
594
- plocals->call_frame = old_call_frame;
595
- return call_frame.return_value;
596
- }
597
- }
598
- "
599
502
 
600
503
  precode = "
601
504
  struct FASTRUBYTHREADDATA* thread_data = 0;
602
- VALUE saved_rb_stack_chunk = Qnil;
505
+ VALUE saved_rb_stack_chunk = Qnil;
506
+
507
+ VALUE next_recv = plocals->self;
508
+
509
+ #{
510
+ if recv_tree
511
+ to_c recv_tree, "next_recv"
512
+ end
513
+ };
603
514
 
604
- pframe->next_recv = #{recv_tree ? to_c(recv_tree) : "plocals->self"};
515
+ pframe->next_recv = next_recv;
605
516
  #ifdef RUBY_1_8
606
517
  NODE* node = rb_method_node(CLASS_OF(pframe->next_recv), #{intern_num mname});
607
518
  #endif
@@ -639,9 +550,9 @@ module FastRuby
639
550
 
640
551
 
641
552
  funcall_call_code = "
642
- return #{
553
+ #{
643
554
  frame_call(
644
- protected_block(inline_block("
555
+ "ret = " + protected_block("
645
556
 
646
557
  void* caller_func;
647
558
  void* block_func;
@@ -662,21 +573,21 @@ module FastRuby
662
573
  node == #{@lambda_node_gvar}
663
574
  ) {
664
575
 
665
- caller_func = #{anonymous_function(&rb_funcall_caller_code_with_lambda)};
666
- block_func = #{anonymous_function(&rb_funcall_block_code_with_lambda)};
576
+ caller_func = #{anonymous_function(:lambda,&rb_funcall_caller_code)};
577
+ block_func = #{anonymous_function(:lambda,&rb_funcall_block_code)};
667
578
  } else if (node == #{@procnew_node_gvar} && pframe->next_recv == rb_cProc) {
668
- caller_func = #{anonymous_function(&rb_funcall_caller_code_with_lambda)};
669
- block_func = #{anonymous_function(&rb_funcall_block_code_proc_new)};
579
+ caller_func = #{anonymous_function(:lambda,&rb_funcall_caller_code)};
580
+ block_func = #{anonymous_function(:proc_new,&rb_funcall_block_code)};
670
581
  } else if (node == #{@callcc_node_gvar}) {
671
- caller_func = #{anonymous_function(&rb_funcall_caller_code)};
672
- block_func = #{anonymous_function(&rb_funcall_block_code_callcc)};
582
+ caller_func = #{anonymous_function(:normal,&rb_funcall_caller_code)};
583
+ block_func = #{anonymous_function(:callcc,&rb_funcall_block_code)};
673
584
  } else {
674
- caller_func = #{anonymous_function(&rb_funcall_caller_code)};
675
- block_func = #{anonymous_function(&rb_funcall_block_code)};
585
+ caller_func = #{anonymous_function(:normal,&rb_funcall_caller_code)};
586
+ block_func = #{anonymous_function(:normal,&rb_funcall_block_code)};
676
587
  }
677
588
 
678
589
 
679
- VALUE ret = rb_iterate(
590
+ last_expression = rb_iterate(
680
591
  caller_func,
681
592
  (VALUE)pframe,
682
593
  block_func,
@@ -688,7 +599,7 @@ module FastRuby
688
599
  current_plocals = pframe->thread_data->last_plocals;
689
600
  while (current_plocals) {
690
601
  current_plocals->active = Qfalse;
691
- current_plocals = (typeof(current_plocals))FIX2LONG(current_plocals->parent_locals);
602
+ current_plocals = (typeof(current_plocals))(current_plocals->parent_locals);
692
603
  }
693
604
 
694
605
  // restore last_plocals
@@ -699,57 +610,83 @@ module FastRuby
699
610
 
700
611
  while (current_plocals) {
701
612
  current_plocals->active = Qtrue;
702
- current_plocals = (typeof(current_plocals))FIX2LONG(current_plocals->parent_locals);
613
+ current_plocals = (typeof(current_plocals))(current_plocals->parent_locals);
703
614
  }
704
615
  }
705
-
706
- return ret;
707
- "), true), precode, postcode
616
+ ", true), precode, postcode
708
617
  )
709
618
  };
710
619
  "
711
620
 
712
621
  recvtype = nil if call_args_tree.size > 1 ? call_args_tree.last[0] == :splat : false
713
622
  unless recvtype
714
- inline_block "
715
- #{funcall_call_code}
716
- "
623
+ if result_var
624
+ "#{result_var} = #{funcall_call_code};"
625
+ else
626
+ funcall_call_code
627
+ end
717
628
  else
718
629
  encoded_address = encode_address(recvtype,signature,mname,call_tree,inference_complete,convention_global_name)
719
630
 
720
- fastruby_call_code = if call_args_tree.size > 1
631
+ if call_args_tree.size > 1
721
632
  value_cast = ( ["VALUE"]*(call_tree[3].size) ).join(",") + ", VALUE, VALUE"
722
-
723
- "
724
- // call to #{call_tree[2]}
725
- #{call_frame_struct_code}
726
-
727
- VALUE ret = ((VALUE(*)(#{value_cast}))#{encoded_address})(#{str_recv}, (VALUE)&block, (VALUE)&call_frame, #{str_called_code_args});
728
- plocals->call_frame = old_call_frame;
729
- return ret;
730
- "
633
+ strargs = "," + (0..call_args_tree.size-2).map{|i| "arg#{i}"}.join(",")
731
634
  else
732
- "
733
- #{call_frame_struct_code}
635
+ value_cast = "VALUE,VALUE,VALUE"
636
+ strargs = ""
637
+ end
734
638
 
639
+ fastruby_call_code = "
735
640
  // call to #{call_tree[2]}
736
- VALUE ret = ((VALUE(*)(VALUE,VALUE,VALUE))#{encoded_address})(#{str_recv}, (VALUE)&block, (VALUE)&call_frame);
737
- plocals->call_frame = old_call_frame;
738
- return ret;
641
+ #{
642
+ if call_args_tree.size > 1
643
+ str_evaluate_args
644
+ end
645
+ };
646
+
647
+ VALUE recv = plocals->self;
648
+
649
+ #{
650
+ if recv_tree
651
+ to_c recv_tree, "recv"
652
+ end
653
+ }
654
+
655
+ ret = ((VALUE(*)(#{value_cast}))#{encoded_address})(recv, (VALUE)&block, (VALUE)&call_frame #{strargs});
739
656
  "
740
- end
741
657
 
742
- inline_block "
658
+ code = "
743
659
  if (#{@last_address_name} == 0) {
744
- #{funcall_call_code}
660
+ return #{funcall_call_code};
745
661
  } else {
662
+ #{if recvtype and inference_complete
663
+ "if (*#{@last_address_name} == 0) {
664
+ rb_funcall(#{literal_value recvtype},#{intern_num :build}, 2, #{literal_value signature}, #{literal_value mname});
665
+ }
666
+ "
667
+ end
668
+ }
746
669
  if (*#{@last_address_name} == 0) {
747
- #{funcall_call_code}
670
+ return #{funcall_call_code};
748
671
  } else {
749
672
  #{fastruby_call_code}
750
673
  }
751
674
  }
752
675
  "
676
+
677
+ fastruby_precode = " #{@block_struct} block;
678
+
679
+ block.block_function_address = ((void*)#{anonymous_function(&block_code)});
680
+ block.block_function_param = ((void*)plocals);
681
+ block.proc = Qnil;
682
+ "
683
+
684
+ if result_var
685
+ "#{result_var} = #{frame_call(code,fastruby_precode,"")}"
686
+ else
687
+ frame_call(code,fastruby_precode,"")
688
+ end
689
+
753
690
  end
754
691
  end
755
692
  end