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
@@ -25,7 +25,7 @@ require "fastruby/method_extension"
25
25
  require "fastruby/set_tree"
26
26
  require "fastruby/exceptions"
27
27
  require "fastruby/translator/translator_modules"
28
-
28
+ require "fastruby/translator/scope_mode_helper"
29
29
 
30
30
  module FastRuby
31
31
  class Context
@@ -65,6 +65,7 @@ module FastRuby
65
65
  @block_struct = "struct {
66
66
  void* block_function_address;
67
67
  void* block_function_param;
68
+ VALUE proc;
68
69
  }"
69
70
 
70
71
  extra_code << "
@@ -83,6 +84,9 @@ module FastRuby
83
84
  #define FASTRUBY_TAG_RETRY 0x85
84
85
  #define TAG_RAISE 0x6
85
86
 
87
+ # define PTR2NUM(x) (ULONG2NUM((unsigned long)(x)))
88
+ # define NUM2PTR(x) ((void*)(NUM2ULONG(x)))
89
+
86
90
  #ifndef __INLINE_FASTRUBY_BASE
87
91
  #include \"#{FastRuby.fastruby_load_path}/../ext/fastruby_base/fastruby_base.inl\"
88
92
  #define __INLINE_FASTRUBY_BASE
@@ -142,7 +146,7 @@ module FastRuby
142
146
  #{@frame_struct}* pframe;
143
147
  pframe = (typeof(pframe))_parent_frame;
144
148
 
145
- return #{protected_block("rb_yield_splat(*(VALUE*)yield_args_p)",true,"yield_args_p",true)};
149
+ return #{protected_block("last_expression = rb_yield_splat(*(VALUE*)yield_args_p)",true,"yield_args_p",true)};
146
150
  }"
147
151
 
148
152
  extra_code << "static VALUE _rb_ivar_set(VALUE recv,ID idvar, VALUE value) {
@@ -179,15 +183,26 @@ module FastRuby
179
183
  end
180
184
  end
181
185
 
182
- def to_c(tree)
186
+ def to_c(tree, result_variable = nil)
183
187
  return "Qnil" unless tree
184
- send("to_c_" + tree[0].to_s, tree);
188
+
189
+ mname = "to_c_" + tree[0].to_s
190
+
191
+ if result_variable
192
+ if method(mname).arity == 1
193
+ "#{result_variable} = #{send(mname, tree)};\n"
194
+ else
195
+ send(mname, tree, result_variable)
196
+ end
197
+ else
198
+ send(mname, tree)
199
+ end
185
200
  end
186
201
 
187
- def anonymous_function
202
+ def anonymous_function(*x)
188
203
 
189
204
  name = "anonymous" + rand(10000000).to_s
190
- extra_code << yield(name)
205
+ extra_code << yield(name,*x)
191
206
 
192
207
  name
193
208
  end
@@ -195,10 +210,10 @@ module FastRuby
195
210
  def frame_call(inner_code, precode = "", postcode = "")
196
211
  inline_block "
197
212
 
198
-
213
+ volatile VALUE ret = Qnil;
199
214
  // create a call_frame
200
215
  #{@frame_struct} call_frame;
201
- typeof(call_frame)* old_pframe = (void*)pframe;
216
+ typeof(call_frame)* volatile old_pframe = (void*)pframe;
202
217
 
203
218
  pframe = (typeof(pframe))&call_frame;
204
219
 
@@ -209,8 +224,8 @@ module FastRuby
209
224
  call_frame.thread_data = old_pframe->thread_data;
210
225
  if (call_frame.thread_data == 0) call_frame.thread_data = rb_current_thread_data();
211
226
 
212
- VALUE old_call_frame = plocals->call_frame;
213
- plocals->call_frame = LONG2FIX(&call_frame);
227
+ void* volatile old_call_frame = plocals->call_frame;
228
+ plocals->call_frame = &call_frame;
214
229
 
215
230
  #{precode}
216
231
 
@@ -235,7 +250,7 @@ module FastRuby
235
250
  }
236
251
 
237
252
 
238
- VALUE ret = #{inner_code};
253
+ #{inner_code};
239
254
 
240
255
  #{postcode}
241
256
 
@@ -246,14 +261,15 @@ module FastRuby
246
261
 
247
262
  def initialize_method_structs(args_tree)
248
263
  @locals_struct = "struct {
249
- VALUE return_value;
250
- VALUE parent_locals;
251
- VALUE pframe;
252
- VALUE block_function_address;
253
- VALUE block_function_param;
254
- VALUE call_frame;
264
+ int size;
265
+ void* call_frame;
266
+ void* parent_locals;
267
+ void* pframe;
268
+ void* block_function_address;
269
+ void* block_function_param;
255
270
  VALUE active;
256
271
  VALUE targetted;
272
+ VALUE return_value;
257
273
  #{@locals.map{|l| "VALUE #{l};\n"}.join}
258
274
  }"
259
275
 
@@ -307,9 +323,9 @@ module FastRuby
307
323
  rb_method_hash = rb_funcall(#{literal_value klass}, #{intern_num :method_hash},1,#{literal_value method_name});
308
324
 
309
325
  if (rb_method_hash != Qnil) {
310
- VALUE tmp = rb_hash_aref(rb_method_hash, LONG2FIX(id));
326
+ VALUE tmp = rb_hash_aref(rb_method_hash, PTR2NUM(id));
311
327
  if (tmp != Qnil) {
312
- address = (void*)FIX2LONG(tmp);
328
+ address = (void*)NUM2PTR(tmp);
313
329
  }
314
330
  }
315
331
 
@@ -323,8 +339,8 @@ module FastRuby
323
339
  #{intern_num :register_method_value},
324
340
  3,
325
341
  #{literal_value method_name},
326
- LONG2FIX(id),
327
- LONG2FIX(address)
342
+ PTR2NUM(id),
343
+ PTR2NUM(address)
328
344
  );
329
345
  }
330
346
  "
@@ -346,247 +362,173 @@ module FastRuby
346
362
 
347
363
  args_tree = original_args_tree.select{|x| x.to_s[0] != ?&}
348
364
 
349
- if (options[:main])
350
365
  initialize_method_structs(original_args_tree)
366
+
367
+ if options[:main] then
368
+ strargs = if args_tree.size > 1
369
+ "VALUE self, VALUE block, VALUE _parent_frame, #{(0..signature.size-1).map{|x| "VALUE arg#{x}"}.join(",")}"
370
+ else
371
+ "VALUE self, VALUE block, VALUE _parent_frame"
372
+ end
351
373
 
352
- strargs = if args_tree.size > 1
353
- "VALUE self, VALUE block, VALUE _parent_frame, #{(0..signature.size-1).map{|x| "VALUE arg#{x}"}.join(",")}"
354
374
  else
355
- "VALUE self, VALUE block, VALUE _parent_frame"
356
- end
357
-
358
- ret = "VALUE #{@alt_method_name || method_name}(VALUE self) {
359
-
360
- #{@locals_struct} *plocals;
361
- #{@frame_struct} frame;
362
- #{@frame_struct} *pframe;
363
-
364
- frame.parent_frame = 0;
365
- frame.return_value = Qnil;
366
- frame.rescue = 0;
367
- frame.targetted = 0;
368
- frame.thread_data = rb_current_thread_data();
369
-
370
-
371
- int stack_chunk_instantiated = 0;
372
- VALUE rb_previous_stack_chunk = Qnil;
373
- VALUE rb_stack_chunk = frame.thread_data->rb_stack_chunk;
374
- struct STACKCHUNK* stack_chunk = 0;
375
-
376
- if (rb_stack_chunk != Qnil) {
377
- Data_Get_Struct(rb_stack_chunk,struct STACKCHUNK,stack_chunk);
378
- }
379
-
380
- if (stack_chunk == 0 || (stack_chunk == 0 ? 0 : stack_chunk_frozen(stack_chunk)) ) {
381
- rb_previous_stack_chunk = rb_stack_chunk;
382
- rb_gc_register_address(&rb_stack_chunk);
383
- stack_chunk_instantiated = 1;
384
-
385
- rb_stack_chunk = rb_stack_chunk_create(Qnil);
386
- frame.thread_data->rb_stack_chunk = rb_stack_chunk;
387
-
388
- rb_ivar_set(rb_stack_chunk, #{intern_num :_parent_stack_chunk}, rb_previous_stack_chunk);
389
-
390
- Data_Get_Struct(rb_stack_chunk,struct STACKCHUNK,stack_chunk);
391
- }
392
-
393
- int previous_stack_position = stack_chunk_get_current_position(stack_chunk);
394
-
395
- plocals = (typeof(plocals))stack_chunk_alloc(stack_chunk ,sizeof(typeof(*plocals))/sizeof(void*));
396
375
 
397
- plocals->parent_locals = LONG2FIX(frame.thread_data->last_plocals);
398
- void* old_parent_locals = frame.thread_data->last_plocals;
399
- frame.thread_data->last_plocals = plocals;
376
+ strargs = "VALUE self, VALUE block, VALUE _parent_frame, int argc, VALUE* argv"
400
377
 
401
- plocals->active = Qtrue;
402
- plocals->targetted = Qfalse;
403
- plocals->pframe = LONG2FIX(&frame);
404
- frame.plocals = plocals;
405
-
406
- pframe = (void*)&frame;
407
-
408
- VALUE last_expression = Qnil;
409
-
410
- int aux = setjmp(pframe->jmp);
411
- if (aux != 0) {
412
- stack_chunk_set_current_position(stack_chunk, previous_stack_position);
413
-
414
- if (stack_chunk_instantiated) {
415
- rb_gc_unregister_address(&rb_stack_chunk);
416
- frame.thread_data->rb_stack_chunk = rb_previous_stack_chunk;
378
+ splat_arg = args_tree[1..-1].find{|x| x.to_s.match(/\*/) }
379
+
380
+ maxargnum = args_tree[1..-1].count{ |x|
381
+ if x.instance_of? Symbol
382
+ not x.to_s.match(/\*/) and not x.to_s.match(/\&/)
383
+ else
384
+ false
385
+ end
417
386
  }
418
-
419
- plocals->active = Qfalse;
420
- frame.thread_data->last_plocals = old_parent_locals;
421
- return plocals->return_value;
422
- }
423
-
424
- plocals->self = self;
425
-
426
- #{args_tree[1..-1].map { |arg|
427
- arg = arg.to_s
428
- arg.gsub!("*","")
429
- "plocals->#{arg} = #{arg};\n"
430
- }.join("") }
431
-
432
- plocals->block_function_address = LONG2FIX(0);
433
- plocals->block_function_param = LONG2FIX(Qnil);
434
- plocals->call_frame = LONG2FIX(0);
435
-
436
- VALUE ret = #{to_c impl_tree};
437
- stack_chunk_set_current_position(stack_chunk, previous_stack_position);
438
-
439
- if (stack_chunk_instantiated) {
440
- rb_gc_unregister_address(&rb_stack_chunk);
441
- frame.thread_data->rb_stack_chunk = rb_previous_stack_chunk;
442
- }
443
-
444
- plocals->active = Qfalse;
445
-
446
- frame.thread_data->last_plocals = old_parent_locals;
447
- return ret;
448
-
449
- }"
450
-
451
- add_main
452
- extra_code << ret
453
- else
454
-
455
- initialize_method_structs(original_args_tree)
456
-
457
- strargs = "VALUE self, VALUE block, VALUE _parent_frame, int argc, VALUE* argv"
458
-
459
- splat_arg = args_tree[1..-1].find{|x| x.to_s.match(/\*/) }
460
-
461
- maxargnum = args_tree[1..-1].count{ |x|
462
- if x.instance_of? Symbol
463
- not x.to_s.match(/\*/) and not x.to_s.match(/\&/)
464
- else
465
- false
387
+
388
+ minargnum = maxargnum
389
+
390
+ args_tree[1..-1].each do |subtree|
391
+ unless subtree.instance_of? Symbol
392
+ if subtree[0] == :block
393
+ minargnum = minargnum - (subtree.size-1)
394
+ end
466
395
  end
467
- }
468
-
469
- minargnum = maxargnum
396
+ end
470
397
 
471
- args_tree[1..-1].each do |subtree|
472
- unless subtree.instance_of? Symbol
473
- if subtree[0] == :block
474
- minargnum = minargnum - (subtree.size-1)
475
- end
398
+ if args_tree[1..-1].find{|x| x.to_s.match(/\*/)}
399
+ maxargnum = 2147483647
476
400
  end
477
- end
478
-
479
- if args_tree[1..-1].find{|x| x.to_s.match(/\*/)}
480
- maxargnum = 2147483647
481
- end
482
-
483
- read_arguments_code = ""
484
-
485
-
486
- validate_arguments_code = if signature.size-1 < minargnum
487
- "
488
- rb_raise(rb_eArgError, \"wrong number of arguments (#{signature.size-1} for #{minargnum})\");
489
- "
490
- elsif signature.size-1 > maxargnum
491
- "
492
- rb_raise(rb_eArgError, \"wrong number of arguments (#{signature.size-1} for #{maxargnum})\");
493
- "
494
- else
495
-
496
- default_block_tree = args_tree[1..-1].find{|subtree|
497
- unless subtree.instance_of? Symbol
498
- if subtree[0] == :block
499
- next true
401
+
402
+ read_arguments_code = ""
403
+
404
+
405
+ validate_arguments_code = if signature.size-1 < minargnum
406
+ "
407
+ rb_raise(rb_eArgError, \"wrong number of arguments (#{signature.size-1} for #{minargnum})\");
408
+ "
409
+ elsif signature.size-1 > maxargnum
410
+ "
411
+ rb_raise(rb_eArgError, \"wrong number of arguments (#{signature.size-1} for #{maxargnum})\");
412
+ "
413
+ else
414
+
415
+ default_block_tree = args_tree[1..-1].find{|subtree|
416
+ unless subtree.instance_of? Symbol
417
+ if subtree[0] == :block
418
+ next true
419
+ end
500
420
  end
501
- end
502
-
503
- false
504
- }
505
-
506
- i = -1
507
-
508
- normalargsnum = args_tree[1..-1].count{|subtree|
509
- if subtree.instance_of? Symbol
510
- unless subtree.to_s.match(/\*/) or subtree.to_s.match(/\&/)
511
- next true
421
+
422
+ false
423
+ }
424
+
425
+ i = -1
426
+
427
+ normalargsnum = args_tree[1..-1].count{|subtree|
428
+ if subtree.instance_of? Symbol
429
+ unless subtree.to_s.match(/\*/) or subtree.to_s.match(/\&/)
430
+ next true
431
+ end
512
432
  end
513
- end
514
-
515
- false
516
- }
517
-
518
- read_arguments_code = args_tree[1..-1].map { |arg_|
519
- arg = arg_.to_s
520
- i = i + 1
521
-
522
- if i < normalargsnum
523
- if i < signature.size-1
524
- "plocals->#{arg} = argv[#{i}];\n"
525
- else
526
433
 
527
- if default_block_tree
528
- initialize_tree = default_block_tree[1..-1].find{|subtree| subtree[1] == arg_}
529
- if initialize_tree
530
- to_c(initialize_tree) + ";\n"
434
+ false
435
+ }
436
+
437
+ read_arguments_code = args_tree[1..-1].map { |arg_|
438
+ arg = arg_.to_s
439
+ i = i + 1
440
+
441
+ if i < normalargsnum
442
+ if i < signature.size-1
443
+ "plocals->#{arg} = argv[#{i}];\n"
444
+ else
445
+
446
+ if default_block_tree
447
+ initialize_tree = default_block_tree[1..-1].find{|subtree| subtree[1] == arg_}
448
+ if initialize_tree
449
+ to_c(initialize_tree) + ";\n"
450
+ else
451
+ ""
452
+ end
531
453
  else
532
- ""
454
+ ";\n"
533
455
  end
534
- else
535
- ";\n"
536
456
  end
537
- end
538
- else
539
- ""
540
- end
541
- }.join("")
542
-
543
- if splat_arg
544
- if signature.size-1 < normalargsnum then
545
- read_arguments_code << "
546
- plocals->#{splat_arg.to_s.gsub("*","")} = rb_ary_new3(0);
547
- "
548
457
  else
549
- read_arguments_code << "
550
- plocals->#{splat_arg.to_s.gsub("*","")} = rb_ary_new4(
551
- #{(signature.size-1) - (normalargsnum)}, argv+#{normalargsnum}
552
- );
553
- "
458
+ ""
554
459
  end
555
-
556
- end
557
-
558
-
559
- ""
560
- end
561
-
562
- if block_argument
460
+ }.join("")
461
+
462
+ if splat_arg
463
+ if signature.size-1 < normalargsnum then
464
+ read_arguments_code << "
465
+ plocals->#{splat_arg.to_s.gsub("*","")} = rb_ary_new3(0);
466
+ "
467
+ else
468
+ read_arguments_code << "
469
+ plocals->#{splat_arg.to_s.gsub("*","")} = rb_ary_new4(
470
+ #{(signature.size-1) - (normalargsnum)}, argv+#{normalargsnum}
471
+ );
472
+ "
473
+ end
474
+
475
+ end
476
+
477
+
478
+ ""
479
+ end
480
+
481
+ if block_argument
482
+
483
+ proc_reyield_block_tree = s(:iter, s(:call, nil, :proc, s(:arglist)), s(:masgn, s(:array, s(:splat, s(:lasgn, :__xproc_arguments)))), s(:yield, s(:splat, s(:lvar, :__xproc_arguments))))
484
+
485
+ require "fastruby/sexp_extension"
486
+
487
+ read_arguments_code << "
488
+ if (pblock ? pblock->proc != Qnil : 0) {
489
+ plocals->#{block_argument.to_s.gsub("&","")} = pblock->proc;
490
+ } else {
491
+ plocals->#{block_argument.to_s.gsub("&","")} = #{to_c FastRuby::FastRubySexp.from_sexp(proc_reyield_block_tree)};
492
+ }
493
+ "
563
494
 
564
- proc_reyield_block_tree = s(:iter, s(:call, nil, :proc, s(:arglist)), s(:masgn, s(:array, s(:splat, s(:lasgn, :__xproc_arguments)))), s(:yield, s(:splat, s(:lvar, :__xproc_arguments))))
495
+ read_arguments_code << "
496
+ if (pblock) {
497
+ rb_ivar_set(plocals->#{block_argument.to_s.gsub("&","")},
498
+ #{intern_num "__block_address"}, PTR2NUM(pblock->block_function_address));
499
+ rb_ivar_set(plocals->#{block_argument.to_s.gsub("&","")},
500
+ #{intern_num "__block_param"}, PTR2NUM(pblock->block_function_param));
501
+ }
565
502
 
566
- require "fastruby/sexp_extension"
503
+ "
504
+ end
567
505
 
568
- read_arguments_code << "
569
- plocals->#{block_argument.to_s.gsub("&","")} = #{to_c FastRuby::FastRubySexp.from_sexp(proc_reyield_block_tree)};
570
- "
571
506
  end
572
507
 
573
- ret = "VALUE #{@alt_method_name || method_name}(#{strargs}) {
508
+ require "fastruby/sexp_extension"
509
+ scope_mode = FastRuby::ScopeModeHelper.get_scope_mode(tree)
510
+
511
+ ret = "VALUE #{@alt_method_name || method_name}(#{options[:main] ? "VALUE self" : strargs}) {
574
512
  #{validate_arguments_code}
575
513
 
576
514
  #{@frame_struct} frame;
577
- #{@frame_struct} *pframe;
515
+ #{@frame_struct} * volatile pframe;
578
516
 
579
- frame.parent_frame = (void*)_parent_frame;
517
+ frame.parent_frame = #{options[:main] ? "0" : "(void*)_parent_frame"};
580
518
  frame.return_value = Qnil;
581
519
  frame.rescue = 0;
582
520
  frame.targetted = 0;
583
- frame.thread_data = ((typeof(pframe))_parent_frame)->thread_data;
521
+ frame.thread_data = #{options[:main] ? "0" : "((typeof(pframe))_parent_frame)->thread_data"};
584
522
  if (frame.thread_data == 0) frame.thread_data = rb_current_thread_data();
585
523
 
586
524
  int stack_chunk_instantiated = 0;
587
- VALUE rb_previous_stack_chunk = Qnil;
525
+
526
+ #{
527
+ if scope_mode == :dag
528
+ "
529
+ volatile VALUE rb_previous_stack_chunk = Qnil;
588
530
  VALUE rb_stack_chunk = frame.thread_data->rb_stack_chunk;
589
- struct STACKCHUNK* stack_chunk = 0;
531
+ struct STACKCHUNK* volatile stack_chunk = 0;
590
532
 
591
533
  if (rb_stack_chunk != Qnil) {
592
534
  Data_Get_Struct(rb_stack_chunk,struct STACKCHUNK,stack_chunk);
@@ -605,43 +547,66 @@ module FastRuby
605
547
  Data_Get_Struct(rb_stack_chunk,struct STACKCHUNK,stack_chunk);
606
548
  }
607
549
 
550
+ #{@locals_struct}* volatile plocals;
608
551
 
609
- #{@locals_struct} *plocals;
610
-
611
- int previous_stack_position = stack_chunk_get_current_position(stack_chunk);
612
-
552
+ volatile int previous_stack_position = stack_chunk_get_current_position(stack_chunk);
613
553
  plocals = (typeof(plocals))stack_chunk_alloc(stack_chunk ,sizeof(typeof(*plocals))/sizeof(void*));
614
554
 
615
- plocals->parent_locals = LONG2FIX(frame.thread_data->last_plocals);
616
- void* old_parent_locals = frame.thread_data->last_plocals;
617
- frame.thread_data->last_plocals = plocals;
555
+ "
556
+ else
557
+ "
558
+ #{@locals_struct} locals;
559
+ typeof(locals) * volatile plocals = &locals;
560
+ "
561
+ end
562
+ }
563
+
564
+ plocals->parent_locals = (frame.thread_data->last_plocals);
565
+ void* volatile old_parent_locals = frame.thread_data->last_plocals;
566
+
567
+ #{
568
+ if scope_mode == :dag
569
+ "frame.thread_data->last_plocals = plocals;\n"
570
+ end
571
+ }
618
572
 
619
573
  frame.plocals = plocals;
620
574
  plocals->active = Qtrue;
621
575
  plocals->targetted = Qfalse;
622
- plocals->pframe = LONG2FIX(&frame);
623
- plocals->call_frame = LONG2FIX(0);
576
+ plocals->pframe = (&frame);
577
+ plocals->call_frame = (0);
624
578
 
625
579
  pframe = (void*)&frame;
626
580
 
627
- #{@block_struct} *pblock;
628
- VALUE last_expression = Qnil;
581
+ #{@block_struct} * volatile pblock;
582
+ volatile VALUE last_expression = Qnil;
629
583
 
630
584
  int aux = setjmp(pframe->jmp);
631
585
  if (aux != 0) {
632
586
  plocals->active = Qfalse;
633
587
 
588
+ #{
589
+ if scope_mode == :dag
590
+ "
634
591
  stack_chunk_set_current_position(stack_chunk, previous_stack_position);
635
592
 
636
593
  if (stack_chunk_instantiated) {
637
594
  rb_gc_unregister_address(&rb_stack_chunk);
638
595
  frame.thread_data->rb_stack_chunk = rb_previous_stack_chunk;
639
596
  }
640
-
641
- if (plocals->targetted == Qfalse || aux != FASTRUBY_TAG_RETURN) {
642
- frame.thread_data->last_plocals = old_parent_locals;
643
-
644
- longjmp(((typeof(pframe))_parent_frame)->jmp,aux);
597
+ "
598
+ end
599
+ }
600
+ #{
601
+ unless options[:main]
602
+ "
603
+ if (plocals->targetted == Qfalse || aux != FASTRUBY_TAG_RETURN) {
604
+ frame.thread_data->last_plocals = old_parent_locals;
605
+
606
+ longjmp(((typeof(pframe))_parent_frame)->jmp,aux);
607
+ }
608
+ "
609
+ end
645
610
  }
646
611
 
647
612
  frame.thread_data->last_plocals = old_parent_locals;
@@ -651,35 +616,47 @@ module FastRuby
651
616
 
652
617
  plocals->self = self;
653
618
 
654
- #{read_arguments_code}
655
-
656
- pblock = (void*)block;
657
- if (pblock) {
658
- plocals->block_function_address = LONG2FIX(pblock->block_function_address);
659
- plocals->block_function_param = LONG2FIX(pblock->block_function_param);
660
- } else {
661
- plocals->block_function_address = LONG2FIX(0);
662
- plocals->block_function_param = LONG2FIX(Qnil);
619
+ #{
620
+ unless options[:main]
621
+ "
622
+ pblock = (void*)block;
623
+ if (pblock) {
624
+ plocals->block_function_address = pblock->block_function_address;
625
+ plocals->block_function_param = pblock->block_function_param;
626
+ } else {
627
+ plocals->block_function_address = (0);
628
+ plocals->block_function_param = 0;
629
+ }
630
+ "
631
+ end
663
632
  }
664
633
 
665
- VALUE __ret = #{to_c impl_tree};
634
+ #{read_arguments_code}
635
+
636
+ #{to_c impl_tree, "last_expression"};
637
+
638
+ local_return:
639
+ #{
640
+ if scope_mode == :dag
641
+ "
666
642
  stack_chunk_set_current_position(stack_chunk, previous_stack_position);
667
643
 
668
644
  if (stack_chunk_instantiated) {
669
645
  rb_gc_unregister_address(&rb_stack_chunk);
670
646
  frame.thread_data->rb_stack_chunk = rb_previous_stack_chunk;
671
647
  }
672
-
648
+ "
649
+ end
650
+ }
673
651
  plocals->active = Qfalse;
674
652
 
675
653
  frame.thread_data->last_plocals = old_parent_locals;
676
654
 
677
- return __ret;
655
+ return last_expression;
678
656
  }"
679
657
 
680
658
  add_main
681
659
  extra_code << ret
682
- end
683
660
 
684
661
  "
685
662
  static VALUE dummy_#{method_name}_#{alt_method_name}_#{rand(1000000000000000000000000000000000)}(VALUE a) {
@@ -698,14 +675,15 @@ module FastRuby
698
675
 
699
676
  @locals = locals
700
677
  @locals_struct = "struct {
701
- VALUE return_value;
702
- VALUE parent_locals;
703
- VALUE pframe;
704
- VALUE block_function_address;
705
- VALUE block_function_param;
706
- VALUE call_frame;
678
+ int size;
679
+ void* call_frame;
680
+ void* parent_locals;
681
+ void* pframe;
682
+ void* block_function_address;
683
+ void* block_function_param;
707
684
  VALUE active;
708
685
  VALUE targetted;
686
+ VALUE return_value;
709
687
  #{@locals.map{|l| "VALUE #{l};\n"}.join}
710
688
  }"
711
689
 
@@ -753,9 +731,9 @@ module FastRuby
753
731
  lvar_type = eval(args[2][1].to_s)
754
732
 
755
733
  @infer_lvar_map[lvar_name] = lvar_type
756
- return ""
734
+ return "Qnil"
757
735
  elsif mname == :block_given?
758
- return "FIX2LONG(plocals->block_function_address) == 0 ? Qfalse : Qtrue"
736
+ return "plocals->block_function_address == 0 ? Qfalse : Qtrue"
759
737
  elsif mname == :inline_c
760
738
 
761
739
  code = args[1][1]
@@ -806,12 +784,32 @@ module FastRuby
806
784
  def inline_block(code, repass_var = nil, nolocals = false)
807
785
  anonymous_function{ |name| "
808
786
  static VALUE #{name}(VALUE param#{repass_var ? ",void* " + repass_var : "" }) {
809
- #{@frame_struct} *pframe = (void*)param;
787
+ #{@frame_struct} * volatile pframe = (void*)param;
810
788
 
811
- #{nolocals ? "" : "#{@locals_struct} *plocals = (void*)pframe->plocals;"}
812
- VALUE last_expression = Qnil;
789
+ #{nolocals ? "" : "#{@locals_struct} * volatile plocals = (void*)pframe->plocals;"}
790
+ volatile VALUE last_expression = Qnil;
813
791
 
814
792
  #{code}
793
+ return Qnil;
794
+
795
+ #{unless nolocals
796
+ "
797
+ local_return:
798
+ plocals->return_value = last_expression;
799
+ plocals->targetted = 1;
800
+ longjmp(pframe->jmp, FASTRUBY_TAG_RETURN);
801
+ return last_expression;
802
+ "
803
+ end
804
+ }
805
+ fastruby_local_redo:
806
+ longjmp(pframe->jmp,FASTRUBY_TAG_REDO);
807
+ return Qnil;
808
+ fastruby_local_next:
809
+ longjmp(pframe->jmp,FASTRUBY_TAG_NEXT);
810
+ return Qnil;
811
+
812
+
815
813
  }
816
814
  "
817
815
  } + "((VALUE)pframe#{repass_var ? ", " + repass_var : "" })"
@@ -830,7 +828,7 @@ module FastRuby
830
828
 
831
829
  #{@frame_struct} frame;
832
830
 
833
- typeof(frame)* pframe;
831
+ typeof(frame)* volatile pframe;
834
832
 
835
833
  #{if repass_var
836
834
  "typeof(frame)* parent_frame = ((typeof(pframe))((void**)param)[0]);"
@@ -870,7 +868,9 @@ module FastRuby
870
868
  "VALUE #{repass_var} = (VALUE)((void**)param)[1];"
871
869
  end
872
870
  }
873
- return #{inner_code};
871
+ volatile VALUE last_expression = Qnil;
872
+ #{inner_code};
873
+ return last_expression;
874
874
  }
875
875
  "
876
876
  }
@@ -946,7 +946,9 @@ module FastRuby
946
946
  result = #{rescue_code};
947
947
  #{wrapper_code}
948
948
  } else {
949
- return #{inner_code};
949
+ VALUE last_expression = Qnil;
950
+ #{inner_code};
951
+ return last_expression;
950
952
  }
951
953
 
952
954
  return result;
@@ -983,14 +985,22 @@ module FastRuby
983
985
  elsif value.instance_of? Class
984
986
  container_str = value.to_s.split("::")[0..-2].join("::")
985
987
 
986
- init_extra << "
987
- #{name} = rb_define_class_under(
988
- #{container_str == "" ? "rb_cObject" : literal_value(eval(container_str))}
989
- ,\"#{value.to_s.split("::").last}\"
990
- ,#{value.superclass == Object ? "rb_cObject" : literal_value(value.superclass)});
988
+ str_class_name = value.to_s.split("::").last
991
989
 
992
- rb_funcall(#{name},#{intern_num :gc_register_object},0);
993
- "
990
+ if (str_class_name == "Object")
991
+ init_extra << "
992
+ #{name} = rb_cObject;
993
+ "
994
+ else
995
+ init_extra << "
996
+ #{name} = rb_define_class_under(
997
+ #{container_str == "" ? "rb_cObject" : literal_value(eval(container_str))}
998
+ ,\"#{str_class_name}\"
999
+ ,#{value.superclass == Object ? "rb_cObject" : literal_value(value.superclass)});
1000
+
1001
+ rb_funcall(#{name},#{intern_num :gc_register_object},0);
1002
+ "
1003
+ end
994
1004
  elsif value.instance_of? Array
995
1005
  init_extra << "
996
1006
  #{name} = rb_ary_new3(#{value.size}, #{value.map{|x| literal_value x}.join(",")} );
@@ -1032,7 +1042,7 @@ module FastRuby
1032
1042
  cfunc_address_name = self.add_global_name("void**", 0);
1033
1043
  cfunc_real_address_name = self.add_global_name("void*", 0);
1034
1044
  tree_pointer_name = self.add_global_name("VALUE*", 0);
1035
- args_tree = call_tree[3]
1045
+ args_tree = call_tree[3].reject{|st| st.respond_to?(:node_type) ? st[0] == :block_pass : false}
1036
1046
  method_tree = nil
1037
1047
 
1038
1048
  begin
@@ -1068,7 +1078,7 @@ module FastRuby
1068
1078
  VALUE method_arguments[#{args_tree.size}] = {#{toprocstrargs}};
1069
1079
 
1070
1080
  return #{
1071
- protected_block "rb_funcall(((VALUE*)method_arguments)[0], #{intern_num mname.to_sym}, #{args_tree.size-1}#{inprocstrargs});", false, "method_arguments"
1081
+ protected_block "last_expression = rb_funcall(((VALUE*)method_arguments)[0], #{intern_num mname.to_sym}, #{args_tree.size-1}#{inprocstrargs});", false, "method_arguments"
1072
1082
  };
1073
1083
  }
1074
1084
  "
@@ -1078,7 +1088,7 @@ module FastRuby
1078
1088
  static VALUE #{funcname}(VALUE self,void* block,void* frame#{strargs_signature}){
1079
1089
 
1080
1090
  #{@frame_struct}* pframe = frame;
1081
- VALUE method_arguments[#{args_tree.size}] = {#{toprocstrargs}};
1091
+ VALUE method_arguments[#{args_tree.size+1}] = {#{toprocstrargs},(VALUE)block};
1082
1092
 
1083
1093
  void* fptr = 0;
1084
1094
 
@@ -1097,12 +1107,12 @@ module FastRuby
1097
1107
  fptr = *#{address_name};
1098
1108
 
1099
1109
  #{
1100
- if args_tree.size < 25 and RUBY_VERSION =~ /^1\.8/
1110
+ if args_tree.size < 25
1101
1111
  "
1102
1112
  if (fptr == 0) {
1103
1113
  fptr = *#{cfunc_address_name};
1104
1114
  if (fptr != 0) {
1105
- VALUE params[2] = {self,LONG2FIX(#{args_tree.size-1})};
1115
+ VALUE params[2] = {self,PTR2NUM(#{args_tree.size-1})};
1106
1116
  return ( (VALUE(*)(#{value_cast})) (fptr) )((VALUE)params,(VALUE)block,(VALUE)frame#{inprocstrargs});
1107
1117
  }
1108
1118
  }
@@ -1111,9 +1121,64 @@ module FastRuby
1111
1121
  }
1112
1122
 
1113
1123
  if (fptr == 0) {
1114
- return #{
1115
- protected_block "rb_funcall(((VALUE*)method_arguments)[0], #{intern_num mname.to_sym}, #{args_tree.size-1}#{inprocstrargs});", false, "method_arguments"
1116
- };
1124
+ if (block==0) {
1125
+ return #{
1126
+ protected_block "last_expression = rb_funcall(((VALUE*)method_arguments)[0], #{intern_num mname.to_sym}, #{args_tree.size-1}#{inprocstrargs});", false, "method_arguments"
1127
+ };
1128
+
1129
+ } else {
1130
+ return #{
1131
+ protected_block "
1132
+ #{@block_struct} *pblock;
1133
+ pblock = (typeof(pblock))( ((VALUE*)method_arguments)[#{args_tree.size}] );
1134
+ last_expression = rb_iterate(
1135
+ #{anonymous_function{|name|
1136
+ "
1137
+ static VALUE #{name} (VALUE data) {
1138
+ VALUE* method_arguments = (VALUE*)data;
1139
+ return rb_funcall(
1140
+ ((VALUE*)method_arguments)[0],
1141
+ #{intern_num mname.to_sym},
1142
+ #{args_tree.size-1}#{inprocstrargs});
1143
+ }
1144
+ "
1145
+ }},
1146
+ (VALUE)method_arguments,
1147
+
1148
+ #{anonymous_function{|name|
1149
+ "
1150
+ static VALUE #{name} (VALUE arg_, VALUE param, int argc, VALUE* argv) {
1151
+
1152
+ VALUE arg;
1153
+ #{
1154
+ # TODO: access directly to argc and argv for optimal execution
1155
+ if RUBY_VERSION =~ /^1\.9/
1156
+ "
1157
+ if (TYPE(arg_) == T_ARRAY) {
1158
+ if (_RARRAY_LEN(arg_) <= 1) {
1159
+ arg = rb_ary_new4(argc,argv);
1160
+ } else {
1161
+ arg = arg_;
1162
+ }
1163
+ } else {
1164
+ arg = rb_ary_new4(argc,argv);
1165
+ }
1166
+ "
1167
+ else
1168
+ "arg = arg_;"
1169
+ end
1170
+ }
1171
+
1172
+ return rb_proc_call(param, arg);
1173
+ }
1174
+ "
1175
+ }},
1176
+ pblock->proc
1177
+ );
1178
+ ", false, "method_arguments"
1179
+ };
1180
+ }
1181
+
1117
1182
  } else {
1118
1183
  return ( (VALUE(*)(VALUE,VALUE,VALUE,int,VALUE*)) (fptr) )(self,(VALUE)block,(VALUE)frame,#{args_tree.size-1},method_arguments+1);
1119
1184
  }
@@ -1139,7 +1204,7 @@ module FastRuby
1139
1204
  static VALUE #{funcname}(VALUE* params, void* block,void* frame, #{strargs_signature}){
1140
1205
  VALUE self = params[0];
1141
1206
  VALUE method_arguments[26] = {#{toprocstrargs}};
1142
- return ( (VALUE(*)(int, VALUE*, VALUE)) (#{cfunc_real_address_name}) )(FIX2LONG(params[1]),method_arguments,self);
1207
+ return ( (VALUE(*)(int, VALUE*, VALUE)) (#{cfunc_real_address_name}) )(NUM2ULONG(params[1]),method_arguments,self);
1143
1208
  }
1144
1209
  "
1145
1210
  }
@@ -1147,7 +1212,7 @@ module FastRuby
1147
1212
  cfunc_wrapper_2 = anonymous_function{ |funcname| "
1148
1213
  static VALUE #{funcname}(VALUE* params, void* block,void* frame, #{strargs_signature}){
1149
1214
  VALUE self = params[0];
1150
- VALUE args = rb_ary_new3(FIX2LONG(params[1]),#{toprocstrargs});
1215
+ VALUE args = rb_ary_new3(NUM2ULONG(params[1]),#{toprocstrargs});
1151
1216
  return ( (VALUE(*)(VALUE,VALUE)) (#{cfunc_real_address_name}) )(self,args);
1152
1217
  }
1153
1218
  "
@@ -1171,7 +1236,7 @@ module FastRuby
1171
1236
 
1172
1237
 
1173
1238
  VALUE fastruby_method = rb_funcall(recvtype, #{intern_num :fastruby_method}, 1, mname);
1174
- #{tree_pointer_name} = (VALUE*)FIX2LONG(fastruby_method_tree_pointer(fastruby_method));
1239
+ #{tree_pointer_name} = (VALUE*)NUM2PTR(fastruby_method_tree_pointer(fastruby_method));
1175
1240
 
1176
1241
  ID id;
1177
1242
  ID default_id = rb_intern(\"default\");
@@ -1182,14 +1247,14 @@ module FastRuby
1182
1247
  rb_method_hash = rb_funcall(recvtype, #{intern_num :method_hash},1,mname);
1183
1248
 
1184
1249
  if (rb_method_hash != Qnil) {
1185
- VALUE tmp = rb_hash_aref(rb_method_hash, LONG2FIX(id));
1250
+ VALUE tmp = rb_hash_aref(rb_method_hash, PTR2NUM(id));
1186
1251
  if (tmp != Qnil) {
1187
- address = (void*)FIX2LONG(tmp);
1252
+ address = (void*)NUM2PTR(tmp);
1188
1253
  }
1189
1254
 
1190
- tmp = rb_hash_aref(rb_method_hash, LONG2FIX(default_id));
1255
+ tmp = rb_hash_aref(rb_method_hash, PTR2NUM(default_id));
1191
1256
  if (tmp != Qnil) {
1192
- default_address = (void*)FIX2LONG(tmp);
1257
+ default_address = (void*)NUM2PTR(tmp);
1193
1258
  }
1194
1259
  }
1195
1260
 
@@ -1217,6 +1282,25 @@ module FastRuby
1217
1282
  }
1218
1283
  }
1219
1284
  #endif
1285
+ #ifdef RUBY_1_9
1286
+ rb_method_entry_t* me = rb_method_entry(recvtype,#{intern_num mname});
1287
+ if (me != 0) {
1288
+ rb_method_definition_t* def = me->def;
1289
+
1290
+ if (def->type == VM_METHOD_TYPE_CFUNC) {
1291
+ if (def->body.cfunc.argc == #{args_tree.size-1}) {
1292
+ *default_address = #{cfunc_wrapper};
1293
+ #{cfunc_real_address_name} = (void*)def->body.cfunc.func;
1294
+ } else if (def->body.cfunc.argc == -1) {
1295
+ *default_address = #{cfunc_wrapper_1};
1296
+ #{cfunc_real_address_name} = (void*)def->body.cfunc.func;
1297
+ } else if (def->body.cfunc.argc == -2) {
1298
+ *default_address = #{cfunc_wrapper_2};
1299
+ #{cfunc_real_address_name} = (void*)def->body.cfunc.func;
1300
+ }
1301
+ }
1302
+ }
1303
+ #endif
1220
1304
 
1221
1305
  if (recvtype != Qnil) {
1222
1306
  rb_funcall(
@@ -1224,8 +1308,8 @@ module FastRuby
1224
1308
  #{intern_num :register_method_value},
1225
1309
  3,
1226
1310
  #{literal_value mname},
1227
- LONG2FIX(default_id),
1228
- LONG2FIX(default_address)
1311
+ PTR2NUM(default_id),
1312
+ PTR2NUM(default_address)
1229
1313
  );
1230
1314
  }
1231
1315
  }
@@ -1239,8 +1323,8 @@ module FastRuby
1239
1323
  #{intern_num :register_method_value},
1240
1324
  3,
1241
1325
  #{literal_value mname},
1242
- LONG2FIX(id),
1243
- LONG2FIX(address)
1326
+ PTR2NUM(id),
1327
+ PTR2NUM(address)
1244
1328
  );
1245
1329
  }
1246
1330
 
@@ -1301,9 +1385,12 @@ module FastRuby
1301
1385
 
1302
1386
  anonymous_function{ |name| "
1303
1387
  static VALUE #{name}(VALUE param) {
1304
- VALUE last_expression = Qnil;
1305
- #{@frame_struct} frame, *pframe, *parent_frame;
1306
- #{@locals_struct} *plocals;
1388
+ volatile VALUE last_expression = Qnil;
1389
+ #{@frame_struct} frame;
1390
+
1391
+ typeof(frame)* volatile pframe;
1392
+ typeof(frame)* volatile parent_frame;
1393
+ #{@locals_struct}* volatile plocals;
1307
1394
 
1308
1395
  parent_frame = (void*)param;
1309
1396
 
@@ -1337,7 +1424,7 @@ module FastRuby
1337
1424
  #{code};
1338
1425
 
1339
1426
  // restore previous frame
1340
- typeof(pframe) original_frame = pframe;
1427
+ volatile typeof(pframe) original_frame = pframe;
1341
1428
  pframe = parent_frame;
1342
1429
  #{not_jmp_code};
1343
1430