fastruby 0.0.14 → 0.0.15
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.
- data/CHANGELOG +12 -0
- data/README +0 -2
- data/Rakefile +1 -1
- data/benchmarks/benchmark.rb +1 -0
- data/benchmarks/benchmark5.rb +3 -1
- data/ext/fastruby_base/fastruby_base.inl +2 -0
- data/lib/fastruby/builder.rb +18 -42
- data/lib/fastruby/exceptions.rb +8 -0
- data/lib/fastruby/getlocals.rb +17 -0
- data/lib/fastruby/object.rb +1 -31
- data/lib/fastruby/translator/modules/block.rb +44 -22
- data/lib/fastruby/translator/modules/call.rb +25 -1
- data/lib/fastruby/translator/modules/defn.rb +85 -57
- data/lib/fastruby/translator/modules/iter.rb +159 -46
- data/lib/fastruby/translator/modules/method_group.rb +7 -0
- data/lib/fastruby/translator/translator.rb +224 -245
- data/lib/fastruby.rb +1 -1
- data/lib/targetted +84 -0
- data/spec/block/arguments_spec.rb +214 -0
- data/spec/block/block_as_proc_spec.rb +98 -0
- data/spec/block/callcc_spec.rb +233 -0
- data/spec/block/proc_as_block_spec.rb +111 -0
- data/spec/call/base_call_spec.rb +3 -2
- data/spec/defn/default_args_spec.rb +303 -0
- data/spec/defn/multiple_args_spec.rb +35 -0
- data/spec/exception/base_spec.rb +26 -0
- metadata +10 -4
@@ -49,8 +49,6 @@ module FastRuby
|
|
49
49
|
mobject = nil
|
50
50
|
len = nil
|
51
51
|
|
52
|
-
extra_inference = {}
|
53
|
-
|
54
52
|
if recvtype
|
55
53
|
|
56
54
|
inference_complete = true
|
@@ -64,31 +62,6 @@ module FastRuby
|
|
64
62
|
inference_complete = false
|
65
63
|
end
|
66
64
|
end
|
67
|
-
|
68
|
-
if recvtype.respond_to? :fastruby_method and inference_complete
|
69
|
-
method_tree = nil
|
70
|
-
begin
|
71
|
-
method_tree = recvtype.instance_method(call_tree[2]).fastruby.tree
|
72
|
-
rescue NoMethodError
|
73
|
-
end
|
74
|
-
|
75
|
-
if method_tree
|
76
|
-
mobject = recvtype.build(signature, call_tree[2])
|
77
|
-
yield_signature = mobject.yield_signature
|
78
|
-
|
79
|
-
if not args_tree
|
80
|
-
elsif args_tree.first == :lasgn
|
81
|
-
if yield_signature[0]
|
82
|
-
extra_inference[args_tree.last] = yield_signature[0]
|
83
|
-
end
|
84
|
-
elsif args_tree.first == :masgn
|
85
|
-
yield_args = args_tree[1][1..-1].map(&:last)
|
86
|
-
(0...yield_signature.size-1).each do |i|
|
87
|
-
extra_inference[yield_args[i]] = yield_signature[i]
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
65
|
end
|
93
66
|
|
94
67
|
anonymous_impl = tree[3]
|
@@ -103,8 +76,6 @@ module FastRuby
|
|
103
76
|
|
104
77
|
str_impl = ""
|
105
78
|
|
106
|
-
with_extra_inference(extra_inference) do
|
107
|
-
|
108
79
|
on_block do
|
109
80
|
# if impl_tree is a block, implement the last node with a return
|
110
81
|
if anonymous_impl
|
@@ -129,18 +100,41 @@ module FastRuby
|
|
129
100
|
str_impl = "last_expression = Qnil;"
|
130
101
|
end
|
131
102
|
end
|
132
|
-
end
|
133
|
-
|
134
103
|
|
135
104
|
if not args_tree
|
136
|
-
str_arg_initialization = ""
|
137
105
|
elsif args_tree.first == :lasgn
|
138
|
-
str_arg_initialization
|
106
|
+
str_arg_initialization << "plocals->#{args_tree[1]} = arg;"
|
139
107
|
elsif args_tree.first == :masgn
|
140
|
-
|
141
|
-
|
108
|
+
|
109
|
+
str_arg_initialization << "
|
110
|
+
{
|
111
|
+
if (TYPE(arg) != T_ARRAY) {
|
112
|
+
if (arg != Qnil) {
|
113
|
+
arg = rb_ary_new4(1,&arg);
|
114
|
+
} else {
|
115
|
+
arg = rb_ary_new2(0);
|
116
|
+
}
|
117
|
+
} else if (RARRAY(arg)->len <= 1) {
|
118
|
+
arg = rb_ary_new4(1,&arg);
|
119
|
+
}
|
120
|
+
}
|
121
|
+
"
|
122
|
+
|
123
|
+
arguments = args_tree[1][1..-1]
|
124
|
+
|
142
125
|
(0..arguments.size-1).each do |i|
|
143
|
-
|
126
|
+
arg = arguments[i]
|
127
|
+
if arg[0] == :lasgn
|
128
|
+
str_arg_initialization << "plocals->#{arguments[i].last} = rb_ary_entry(arg,#{i});\n"
|
129
|
+
elsif arg[0] == :splat
|
130
|
+
str_arg_initialization << "plocals->#{arg.last.last} = rb_ary_new2(RARRAY(arg)->len-#{i});\n
|
131
|
+
|
132
|
+
int i;
|
133
|
+
for (i=#{i};i<RARRAY(arg)->len;i++){
|
134
|
+
rb_ary_store(plocals->#{arg.last.last},i-#{i},rb_ary_entry(arg,i));
|
135
|
+
}
|
136
|
+
"
|
137
|
+
end
|
144
138
|
end
|
145
139
|
end
|
146
140
|
rb_funcall_caller_code = nil
|
@@ -339,7 +333,7 @@ module FastRuby
|
|
339
333
|
rb_raise(rb_eLocalJumpError,\"return from proc-closure\");
|
340
334
|
} else {
|
341
335
|
((typeof(plocals))(pframe->plocals))->call_frame = old_call_frame;
|
342
|
-
|
336
|
+
frb_jump_tag(aux);
|
343
337
|
}
|
344
338
|
} else {
|
345
339
|
rb_raise(rb_eLocalJumpError, \"unexpected return\");
|
@@ -382,7 +376,7 @@ module FastRuby
|
|
382
376
|
} else if (aux == FASTRUBY_TAG_REDO) {
|
383
377
|
// do nothing and let execute the block again
|
384
378
|
} else {
|
385
|
-
|
379
|
+
frb_jump_tag(aux);
|
386
380
|
return frame.return_value;
|
387
381
|
}
|
388
382
|
}
|
@@ -396,6 +390,48 @@ module FastRuby
|
|
396
390
|
"
|
397
391
|
}
|
398
392
|
|
393
|
+
rb_funcall_block_code_callcc = proc { |name| "
|
394
|
+
static VALUE #{name}(VALUE arg, VALUE _plocals) {
|
395
|
+
// block for call to #{call_tree[2]}
|
396
|
+
VALUE last_expression = Qnil;
|
397
|
+
|
398
|
+
#{@frame_struct} frame;
|
399
|
+
#{@frame_struct} *pframe = (void*)&frame;
|
400
|
+
#{@locals_struct} *plocals = (void*)_plocals;
|
401
|
+
|
402
|
+
frame.plocals = plocals;
|
403
|
+
frame.parent_frame = 0;
|
404
|
+
frame.return_value = Qnil;
|
405
|
+
frame.rescue = 0;
|
406
|
+
frame.targetted = 0;
|
407
|
+
frame.thread_data = rb_current_thread_data();
|
408
|
+
|
409
|
+
int aux = setjmp(frame.jmp);
|
410
|
+
if (aux != 0) {
|
411
|
+
|
412
|
+
if (aux == FASTRUBY_TAG_NEXT) {
|
413
|
+
return pframe->thread_data->accumulator;
|
414
|
+
} else if (aux == FASTRUBY_TAG_REDO) {
|
415
|
+
// do nothing and let execute the block again
|
416
|
+
} else {
|
417
|
+
frb_jump_tag(aux);
|
418
|
+
return frame.return_value;
|
419
|
+
}
|
420
|
+
}
|
421
|
+
|
422
|
+
if (rb_obj_is_kind_of(arg,rb_cCont)) {
|
423
|
+
struct FASTRUBYTHREADDATA* thread_data = frame.thread_data;
|
424
|
+
rb_ivar_set(arg,#{intern_num :__stack_chunk},thread_data->rb_stack_chunk);
|
425
|
+
}
|
426
|
+
|
427
|
+
#{str_arg_initialization}
|
428
|
+
#{str_impl}
|
429
|
+
|
430
|
+
return last_expression;
|
431
|
+
}
|
432
|
+
"
|
433
|
+
}
|
434
|
+
|
399
435
|
|
400
436
|
fastruby_str_arg_initialization = ""
|
401
437
|
|
@@ -404,10 +440,22 @@ module FastRuby
|
|
404
440
|
elsif args_tree.first == :lasgn
|
405
441
|
fastruby_str_arg_initialization = "plocals->#{args_tree[1]} = argv[0];"
|
406
442
|
elsif args_tree.first == :masgn
|
407
|
-
arguments = args_tree[1][1..-1]
|
408
|
-
|
443
|
+
arguments = args_tree[1][1..-1]
|
444
|
+
|
409
445
|
(0..arguments.size-1).each do |i|
|
410
|
-
|
446
|
+
arg = arguments[i]
|
447
|
+
if arg[0] == :lasgn
|
448
|
+
fastruby_str_arg_initialization << "plocals->#{arg.last} = #{i} < argc ? argv[#{i}] : Qnil;\n"
|
449
|
+
elsif arg[0] == :splat
|
450
|
+
fastruby_str_arg_initialization << "plocals->#{arg.last.last} = rb_ary_new2(#{arguments.size-1-i});\n
|
451
|
+
{
|
452
|
+
int i;
|
453
|
+
for (i=#{i};i<argc;i++){
|
454
|
+
rb_ary_store(plocals->#{arg.last.last},i-#{i},argv[i]);
|
455
|
+
}
|
456
|
+
}
|
457
|
+
"
|
458
|
+
end
|
411
459
|
end
|
412
460
|
end
|
413
461
|
|
@@ -496,16 +544,55 @@ module FastRuby
|
|
496
544
|
}
|
497
545
|
"
|
498
546
|
|
547
|
+
precode = "
|
548
|
+
struct FASTRUBYTHREADDATA* thread_data = 0;
|
549
|
+
VALUE saved_rb_stack_chunk = Qnil;
|
550
|
+
|
551
|
+
pframe->next_recv = #{recv_tree ? to_c(recv_tree) : "plocals->self"};
|
552
|
+
|
553
|
+
NODE* node = rb_method_node(CLASS_OF(pframe->next_recv), #{intern_num mname});
|
554
|
+
|
555
|
+
if (node == #{@callcc_node_gvar}) {
|
556
|
+
|
557
|
+
// freeze all stacks
|
558
|
+
thread_data = rb_current_thread_data();
|
559
|
+
|
560
|
+
if (thread_data != 0) {
|
561
|
+
VALUE rb_stack_chunk = thread_data->rb_stack_chunk;
|
562
|
+
saved_rb_stack_chunk = rb_stack_chunk;
|
563
|
+
|
564
|
+
// freeze the complete chain of stack chunks
|
565
|
+
while (rb_stack_chunk != Qnil) {
|
566
|
+
struct STACKCHUNK* stack_chunk;
|
567
|
+
Data_Get_Struct(rb_stack_chunk,struct STACKCHUNK,stack_chunk);
|
568
|
+
|
569
|
+
stack_chunk_freeze(stack_chunk);
|
570
|
+
|
571
|
+
rb_stack_chunk = rb_ivar_get(rb_stack_chunk,#{intern_num :_parent_stack_chunk});
|
572
|
+
}
|
573
|
+
}
|
574
|
+
}
|
575
|
+
"
|
576
|
+
|
577
|
+
postcode = "
|
578
|
+
if (node == #{@callcc_node_gvar}) {
|
579
|
+
thread_data->rb_stack_chunk = saved_rb_stack_chunk;
|
580
|
+
}
|
581
|
+
"
|
582
|
+
|
583
|
+
|
499
584
|
funcall_call_code = "
|
500
585
|
return #{
|
501
586
|
frame_call(
|
502
587
|
protected_block(inline_block("
|
503
|
-
|
504
|
-
pframe->next_recv = #{recv_tree ? to_c(recv_tree) : "plocals->self"};
|
505
|
-
|
588
|
+
|
506
589
|
NODE* node = rb_method_node(CLASS_OF(pframe->next_recv), #{intern_num mname});
|
507
590
|
void* caller_func;
|
508
591
|
void* block_func;
|
592
|
+
typeof(plocals) current_plocals;
|
593
|
+
|
594
|
+
if (pframe->thread_data == 0) pframe->thread_data = rb_current_thread_data();
|
595
|
+
void* last_plocals = pframe->thread_data->last_plocals;
|
509
596
|
|
510
597
|
if (
|
511
598
|
node == #{@proc_node_gvar} ||
|
@@ -517,18 +604,44 @@ module FastRuby
|
|
517
604
|
} else if (node == #{@procnew_node_gvar} && pframe->next_recv == rb_cProc) {
|
518
605
|
caller_func = #{anonymous_function(&rb_funcall_caller_code_with_lambda)};
|
519
606
|
block_func = #{anonymous_function(&rb_funcall_block_code_proc_new)};
|
607
|
+
} else if (node == #{@callcc_node_gvar}) {
|
608
|
+
caller_func = #{anonymous_function(&rb_funcall_caller_code)};
|
609
|
+
block_func = #{anonymous_function(&rb_funcall_block_code_callcc)};
|
520
610
|
} else {
|
521
611
|
caller_func = #{anonymous_function(&rb_funcall_caller_code)};
|
522
612
|
block_func = #{anonymous_function(&rb_funcall_block_code)};
|
523
613
|
}
|
614
|
+
|
524
615
|
|
525
|
-
|
616
|
+
VALUE ret = rb_iterate(
|
526
617
|
caller_func,
|
527
618
|
(VALUE)pframe,
|
528
619
|
block_func,
|
529
620
|
(VALUE)plocals);
|
530
621
|
|
531
|
-
|
622
|
+
if (node == #{@callcc_node_gvar}) {
|
623
|
+
|
624
|
+
// remove active flags of abandoned stack
|
625
|
+
current_plocals = pframe->thread_data->last_plocals;
|
626
|
+
while (current_plocals) {
|
627
|
+
current_plocals->active = Qfalse;
|
628
|
+
current_plocals = (typeof(current_plocals))FIX2LONG(current_plocals->parent_locals);
|
629
|
+
}
|
630
|
+
|
631
|
+
// restore last_plocals
|
632
|
+
pframe->thread_data->last_plocals = last_plocals;
|
633
|
+
|
634
|
+
// mark all scopes as active
|
635
|
+
current_plocals = last_plocals;
|
636
|
+
|
637
|
+
while (current_plocals) {
|
638
|
+
current_plocals->active = Qtrue;
|
639
|
+
current_plocals = (typeof(current_plocals))FIX2LONG(current_plocals->parent_locals);
|
640
|
+
}
|
641
|
+
}
|
642
|
+
|
643
|
+
return ret;
|
644
|
+
"), true), precode, postcode
|
532
645
|
)
|
533
646
|
};
|
534
647
|
"
|
@@ -112,6 +112,10 @@ private
|
|
112
112
|
|
113
113
|
plocals = (typeof(plocals))stack_chunk_alloc(stack_chunk ,sizeof(typeof(*plocals))/sizeof(void*));
|
114
114
|
|
115
|
+
plocals->parent_locals = LONG2FIX(frame.thread_data->last_plocals);
|
116
|
+
void* old_parent_locals = frame.thread_data->last_plocals;
|
117
|
+
frame.thread_data->last_plocals = plocals;
|
118
|
+
|
115
119
|
frame.plocals = plocals;
|
116
120
|
plocals->active = Qtrue;
|
117
121
|
plocals->self = self;
|
@@ -128,6 +132,9 @@ private
|
|
128
132
|
}
|
129
133
|
|
130
134
|
plocals->active = Qfalse;
|
135
|
+
|
136
|
+
frame.thread_data->last_plocals = old_parent_locals;
|
137
|
+
|
131
138
|
return Qnil;
|
132
139
|
}
|
133
140
|
"
|