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