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