fastruby 0.0.8 → 0.0.9
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 +4 -0
- data/Rakefile +1 -1
- data/lib/fastruby/translator.rb +186 -57
- data/lib/fastruby.rb +1 -1
- data/spec/block/lambda_spec.rb +20 -0
- data/spec/block/proc_spec.rb +248 -0
- metadata +5 -4
data/CHANGELOG
CHANGED
data/Rakefile
CHANGED
data/lib/fastruby/translator.rb
CHANGED
@@ -54,6 +54,7 @@ module FastRuby
|
|
54
54
|
int rescue;
|
55
55
|
VALUE last_error;
|
56
56
|
void* stack_chunk;
|
57
|
+
VALUE next_recv;
|
57
58
|
}"
|
58
59
|
|
59
60
|
@block_struct = "struct {
|
@@ -80,7 +81,15 @@ module FastRuby
|
|
80
81
|
rb_eval_string(#{ruby_code.inspect});
|
81
82
|
"
|
82
83
|
|
84
|
+
@lambda_node_gvar = add_global_name("NODE*", 0);
|
85
|
+
@proc_node_gvar = add_global_name("NODE*", 0);
|
86
|
+
@procnew_node_gvar = add_global_name("NODE*", 0);
|
83
87
|
|
88
|
+
init_extra << "
|
89
|
+
#{@lambda_node_gvar} = rb_method_node(rb_cObject, #{intern_num :lambda});
|
90
|
+
#{@proc_node_gvar} = rb_method_node(rb_cObject, #{intern_num :proc});
|
91
|
+
#{@procnew_node_gvar} = rb_method_node(CLASS_OF(rb_cProc), #{intern_num :new});
|
92
|
+
"
|
84
93
|
|
85
94
|
@common_func = common_func
|
86
95
|
if common_func
|
@@ -324,7 +333,7 @@ module FastRuby
|
|
324
333
|
if call_args_tree.size > 1
|
325
334
|
|
326
335
|
str_called_code_args = call_args_tree[1..-1].map{ |subtree| to_c subtree }.join(",")
|
327
|
-
str_recv =
|
336
|
+
str_recv = "pframe->next_recv"
|
328
337
|
|
329
338
|
str_recv = "plocals->self" unless recv_tree
|
330
339
|
|
@@ -338,12 +347,25 @@ module FastRuby
|
|
338
347
|
"
|
339
348
|
}
|
340
349
|
|
350
|
+
rb_funcall_caller_code_with_lambda = rb_funcall_caller_code
|
341
351
|
else
|
342
|
-
str_recv =
|
352
|
+
str_recv = "pframe->next_recv"
|
343
353
|
str_recv = "plocals->self" unless recv_tree
|
344
354
|
|
345
|
-
|
346
|
-
|
355
|
+
rb_funcall_caller_code = proc { |name| "
|
356
|
+
static VALUE #{name}(VALUE param) {
|
357
|
+
// call to #{call_tree[2]}
|
358
|
+
#{str_lvar_initialization}
|
359
|
+
return rb_funcall(#{str_recv}, #{intern_num call_tree[2]}, 0);
|
360
|
+
}
|
361
|
+
"
|
362
|
+
}
|
363
|
+
|
364
|
+
rb_funcall_caller_code_with_lambda = proc { |name| "
|
365
|
+
static VALUE #{name}(VALUE param) {
|
366
|
+
// call to #{call_tree[2]}
|
367
|
+
#{str_lvar_initialization}
|
368
|
+
VALUE ret = rb_funcall(#{str_recv}, #{intern_num call_tree[2]}, 0);
|
347
369
|
|
348
370
|
// freeze all stacks
|
349
371
|
VALUE current_thread = rb_thread_current();
|
@@ -370,36 +392,32 @@ module FastRuby
|
|
370
392
|
}
|
371
393
|
|
372
394
|
return ret;
|
373
|
-
"
|
374
|
-
else
|
375
|
-
"return rb_funcall(#{str_recv}, #{intern_num call_tree[2]}, 0);"
|
376
|
-
end
|
377
|
-
|
378
|
-
rb_funcall_caller_code = proc { |name| "
|
379
|
-
static VALUE #{name}(VALUE param) {
|
380
|
-
// call to #{call_tree[2]}
|
381
|
-
#{str_lvar_initialization}
|
382
|
-
#{execute_code}
|
383
395
|
}
|
384
396
|
"
|
385
397
|
}
|
386
|
-
end
|
387
398
|
|
388
|
-
|
389
|
-
"
|
390
|
-
// create a fake parent frame representing the lambda method frame and a fake locals scope
|
391
|
-
#{@locals_struct} fake_locals;
|
392
|
-
#{@frame_struct} fake_frame;
|
399
|
+
end
|
393
400
|
|
394
|
-
|
395
|
-
|
401
|
+
rb_funcall_block_code_with_lambda = proc { |name| "
|
402
|
+
static VALUE #{name}(VALUE arg, VALUE _plocals) {
|
403
|
+
// block for call to #{call_tree[2]}
|
404
|
+
VALUE last_expression = Qnil;
|
396
405
|
|
397
|
-
|
406
|
+
#{@frame_struct} frame;
|
407
|
+
#{@frame_struct} *pframe = (void*)&frame;
|
408
|
+
#{@locals_struct} *plocals = (void*)_plocals;
|
398
409
|
|
399
|
-
|
400
|
-
|
410
|
+
frame.plocals = plocals;
|
411
|
+
frame.stack_chunk = 0;
|
412
|
+
frame.parent_frame = 0;
|
413
|
+
frame.return_value = Qnil;
|
414
|
+
frame.target_frame = &frame;
|
415
|
+
frame.exception = Qnil;
|
416
|
+
frame.rescue = 0;
|
401
417
|
|
402
|
-
frame
|
418
|
+
// create a fake parent frame representing the lambda method frame and a fake locals scope
|
419
|
+
VALUE old_call_frame = ((typeof(plocals))(pframe->plocals))->call_frame;
|
420
|
+
((typeof(plocals))(pframe->plocals))->call_frame = LONG2FIX(pframe);
|
403
421
|
|
404
422
|
if (setjmp(frame.jmp) != 0) {
|
405
423
|
|
@@ -407,49 +425,97 @@ module FastRuby
|
|
407
425
|
if (pframe->target_frame == (void*)-3) {
|
408
426
|
return pframe->return_value;
|
409
427
|
} else if (pframe->target_frame == (void*)-1) {
|
410
|
-
rb_funcall(((typeof(
|
428
|
+
rb_funcall(((typeof(plocals))(pframe->plocals))->self, #{intern_num :raise}, 1, frame.exception);
|
411
429
|
return Qnil;
|
412
430
|
} else {
|
413
431
|
if (pframe->target_frame == (void*)FIX2LONG(plocals->pframe)) {
|
414
|
-
((typeof(
|
432
|
+
((typeof(plocals))(pframe->plocals))->call_frame = old_call_frame;
|
415
433
|
return pframe->return_value;
|
416
|
-
} else if (pframe->target_frame == (void*)&fake_frame) {
|
417
|
-
((typeof(fake_locals)*)(pframe->plocals))->call_frame = old_call_frame;
|
418
|
-
return fake_locals.return_value;
|
419
434
|
} else {
|
420
435
|
rb_raise(rb_eLocalJumpError, \"unexpected return\");
|
421
436
|
}
|
422
437
|
}
|
423
438
|
}
|
424
|
-
((typeof(
|
439
|
+
((typeof(plocals))(pframe->plocals))->call_frame = old_call_frame;
|
425
440
|
return frame.return_value;
|
426
441
|
}
|
427
442
|
|
443
|
+
|
444
|
+
|
445
|
+
#{str_arg_initialization}
|
446
|
+
#{str_impl}
|
447
|
+
|
448
|
+
((typeof(plocals))(pframe->plocals))->call_frame = old_call_frame;
|
449
|
+
return last_expression;
|
450
|
+
}
|
428
451
|
"
|
429
|
-
|
430
|
-
"
|
431
|
-
if (setjmp(frame.jmp) != 0) {
|
432
|
-
if (pframe->target_frame != pframe) {
|
433
|
-
if (pframe->target_frame == (void*)-3) {
|
434
|
-
return pframe->return_value;
|
435
|
-
}
|
452
|
+
}
|
436
453
|
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
pframe->exception,
|
442
|
-
LONG2FIX(pframe->target_frame),
|
443
|
-
pframe->return_value
|
444
|
-
);
|
454
|
+
rb_funcall_block_code_proc_new = proc { |name| "
|
455
|
+
static VALUE #{name}(VALUE arg, VALUE _plocals) {
|
456
|
+
// block for call to #{call_tree[2]}
|
457
|
+
VALUE last_expression = Qnil;
|
445
458
|
|
446
|
-
|
459
|
+
#{@frame_struct} frame;
|
460
|
+
#{@frame_struct} *pframe = (void*)&frame;
|
461
|
+
#{@locals_struct} *plocals = (void*)_plocals;
|
462
|
+
|
463
|
+
frame.plocals = plocals;
|
464
|
+
frame.stack_chunk = 0;
|
465
|
+
frame.parent_frame = 0;
|
466
|
+
frame.return_value = Qnil;
|
467
|
+
frame.target_frame = &frame;
|
468
|
+
frame.exception = Qnil;
|
469
|
+
frame.rescue = 0;
|
470
|
+
|
471
|
+
// create a fake parent frame representing the lambda method frame and a fake locals scope
|
472
|
+
VALUE old_call_frame = ((typeof(plocals))(pframe->plocals))->call_frame;
|
473
|
+
((typeof(plocals))(pframe->plocals))->call_frame = LONG2FIX(pframe);
|
474
|
+
|
475
|
+
if (setjmp(frame.jmp) != 0) {
|
476
|
+
if (pframe->target_frame != pframe) {
|
477
|
+
if (pframe->target_frame == (void*)-3) {
|
478
|
+
return pframe->return_value;
|
479
|
+
} else if (pframe->target_frame == (void*)-1) {
|
480
|
+
rb_funcall(((typeof(plocals))(pframe->plocals))->self, #{intern_num :raise}, 1, frame.exception);
|
481
|
+
return Qnil;
|
482
|
+
} else {
|
483
|
+
if (pframe->target_frame == (void*)FIX2LONG(plocals->pframe)) {
|
484
|
+
|
485
|
+
if (plocals->active == Qfalse) {
|
486
|
+
rb_raise(rb_eLocalJumpError,\"return from proc-closure\");
|
487
|
+
} else {
|
488
|
+
((typeof(plocals))(pframe->plocals))->call_frame = old_call_frame;
|
489
|
+
VALUE ex = rb_funcall(
|
490
|
+
#{literal_value FastRuby::Context::UnwindFastrubyFrame},
|
491
|
+
#{intern_num :new},
|
492
|
+
3,
|
493
|
+
pframe->exception,
|
494
|
+
LONG2FIX(pframe->target_frame),
|
495
|
+
pframe->return_value
|
496
|
+
);
|
497
|
+
|
498
|
+
rb_funcall(plocals->self, #{intern_num :raise}, 1, ex);
|
499
|
+
}
|
500
|
+
} else {
|
501
|
+
rb_raise(rb_eLocalJumpError, \"unexpected return\");
|
502
|
+
}
|
503
|
+
}
|
447
504
|
}
|
448
|
-
|
505
|
+
|
506
|
+
rb_raise(rb_eLocalJumpError, \"break from proc-closure\");
|
449
507
|
}
|
450
508
|
|
509
|
+
#{str_arg_initialization}
|
510
|
+
#{str_impl}
|
511
|
+
|
512
|
+
((typeof(plocals))(pframe->plocals))->call_frame = old_call_frame;
|
513
|
+
|
514
|
+
return last_expression;
|
515
|
+
}
|
451
516
|
"
|
452
|
-
|
517
|
+
}
|
518
|
+
|
453
519
|
|
454
520
|
rb_funcall_block_code = proc { |name| "
|
455
521
|
static VALUE #{name}(VALUE arg, VALUE _plocals) {
|
@@ -468,14 +534,30 @@ module FastRuby
|
|
468
534
|
frame.exception = Qnil;
|
469
535
|
frame.rescue = 0;
|
470
536
|
|
471
|
-
|
537
|
+
if (setjmp(frame.jmp) != 0) {
|
538
|
+
if (pframe->target_frame != pframe) {
|
539
|
+
if (pframe->target_frame == (void*)-3) {
|
540
|
+
return pframe->return_value;
|
541
|
+
}
|
542
|
+
|
543
|
+
VALUE ex = rb_funcall(
|
544
|
+
#{literal_value FastRuby::Context::UnwindFastrubyFrame},
|
545
|
+
#{intern_num :new},
|
546
|
+
3,
|
547
|
+
pframe->exception,
|
548
|
+
LONG2FIX(pframe->target_frame),
|
549
|
+
pframe->return_value
|
550
|
+
);
|
551
|
+
|
552
|
+
rb_funcall(plocals->self, #{intern_num :raise}, 1, ex);
|
553
|
+
}
|
554
|
+
return frame.return_value;
|
555
|
+
}
|
472
556
|
|
473
557
|
|
474
558
|
#{str_arg_initialization}
|
475
559
|
#{str_impl}
|
476
560
|
|
477
|
-
#{"((typeof(fake_locals)*)(pframe->plocals))->call_frame = old_call_frame;" if mname == :lambda or mname == :proc}
|
478
|
-
|
479
561
|
return last_expression;
|
480
562
|
}
|
481
563
|
"
|
@@ -617,7 +699,36 @@ module FastRuby
|
|
617
699
|
} else {
|
618
700
|
return #{
|
619
701
|
frame_call(
|
620
|
-
protected_block(
|
702
|
+
protected_block(inline_block("
|
703
|
+
|
704
|
+
pframe->next_recv = #{recv_tree ? to_c(recv_tree) : "plocals->self"};
|
705
|
+
|
706
|
+
NODE* node = rb_method_node(CLASS_OF(pframe->next_recv), #{intern_num mname});
|
707
|
+
void* caller_func;
|
708
|
+
void* block_func;
|
709
|
+
|
710
|
+
if (
|
711
|
+
node == #{@proc_node_gvar} ||
|
712
|
+
node == #{@lambda_node_gvar}
|
713
|
+
) {
|
714
|
+
|
715
|
+
caller_func = #{anonymous_function(&rb_funcall_caller_code_with_lambda)};
|
716
|
+
block_func = #{anonymous_function(&rb_funcall_block_code_with_lambda)};
|
717
|
+
} else if (node == #{@procnew_node_gvar} && pframe->next_recv == rb_cProc) {
|
718
|
+
caller_func = #{anonymous_function(&rb_funcall_caller_code_with_lambda)};
|
719
|
+
block_func = #{anonymous_function(&rb_funcall_block_code_proc_new)};
|
720
|
+
} else {
|
721
|
+
caller_func = #{anonymous_function(&rb_funcall_caller_code)};
|
722
|
+
block_func = #{anonymous_function(&rb_funcall_block_code)};
|
723
|
+
}
|
724
|
+
|
725
|
+
return rb_iterate(
|
726
|
+
caller_func,
|
727
|
+
(VALUE)pframe,
|
728
|
+
block_func,
|
729
|
+
(VALUE)plocals);
|
730
|
+
|
731
|
+
"), true)
|
621
732
|
)
|
622
733
|
};
|
623
734
|
}
|
@@ -735,7 +846,13 @@ module FastRuby
|
|
735
846
|
end
|
736
847
|
|
737
848
|
def to_c_return(tree)
|
738
|
-
|
849
|
+
inline_block "
|
850
|
+
pframe->target_frame = ((typeof(pframe))FIX2LONG(plocals->pframe));
|
851
|
+
plocals->return_value = #{to_c(tree[1])};
|
852
|
+
pframe->return_value = plocals->return_value;
|
853
|
+
longjmp(pframe->jmp, 1);
|
854
|
+
return Qnil;
|
855
|
+
"
|
739
856
|
end
|
740
857
|
|
741
858
|
def to_c_break(tree)
|
@@ -1125,6 +1242,7 @@ module FastRuby
|
|
1125
1242
|
VALUE block_function_address;
|
1126
1243
|
VALUE block_function_param;
|
1127
1244
|
VALUE call_frame;
|
1245
|
+
VALUE active;
|
1128
1246
|
#{@locals.map{|l| "VALUE #{l};\n"}.join}
|
1129
1247
|
#{args_tree[1..-1].map{|arg| "VALUE #{arg};\n"}.join};
|
1130
1248
|
}"
|
@@ -1300,6 +1418,7 @@ module FastRuby
|
|
1300
1418
|
int previous_stack_position = stack_chunk_get_current_position(frame.stack_chunk);
|
1301
1419
|
|
1302
1420
|
plocals = (typeof(plocals))stack_chunk_alloc(frame.stack_chunk ,sizeof(typeof(*plocals))/sizeof(void*));
|
1421
|
+
plocals->active = Qtrue;
|
1303
1422
|
plocals->pframe = LONG2FIX(&frame);
|
1304
1423
|
frame.plocals = plocals;
|
1305
1424
|
|
@@ -1318,9 +1437,11 @@ module FastRuby
|
|
1318
1437
|
|
1319
1438
|
if (pframe->target_frame != pframe) {
|
1320
1439
|
// raise exception
|
1440
|
+
plocals->active = Qfalse;
|
1321
1441
|
return Qnil;
|
1322
1442
|
}
|
1323
1443
|
|
1444
|
+
plocals->active = Qfalse;
|
1324
1445
|
return plocals->return_value;
|
1325
1446
|
}
|
1326
1447
|
|
@@ -1342,6 +1463,7 @@ module FastRuby
|
|
1342
1463
|
stack_chunk_reference_assign(stack_chunk_reference, rb_previous_stack_chunk);
|
1343
1464
|
}
|
1344
1465
|
|
1466
|
+
plocals->active = Qfalse;
|
1345
1467
|
return ret;
|
1346
1468
|
|
1347
1469
|
}"
|
@@ -1395,6 +1517,7 @@ module FastRuby
|
|
1395
1517
|
|
1396
1518
|
plocals = (typeof(plocals))stack_chunk_alloc(frame.stack_chunk ,sizeof(typeof(*plocals))/sizeof(void*));
|
1397
1519
|
frame.plocals = plocals;
|
1520
|
+
plocals->active = Qtrue;
|
1398
1521
|
plocals->pframe = LONG2FIX(&frame);
|
1399
1522
|
plocals->call_frame = LONG2FIX(0);
|
1400
1523
|
|
@@ -1405,6 +1528,8 @@ module FastRuby
|
|
1405
1528
|
|
1406
1529
|
int aux = setjmp(pframe->jmp);
|
1407
1530
|
if (aux != 0) {
|
1531
|
+
plocals->active = Qfalse;
|
1532
|
+
|
1408
1533
|
stack_chunk_set_current_position(frame.stack_chunk, previous_stack_position);
|
1409
1534
|
|
1410
1535
|
if (stack_chunk_instantiated) {
|
@@ -1447,6 +1572,7 @@ module FastRuby
|
|
1447
1572
|
stack_chunk_reference_assign(stack_chunk_reference, rb_previous_stack_chunk);
|
1448
1573
|
}
|
1449
1574
|
|
1575
|
+
plocals->active = Qfalse;
|
1450
1576
|
return __ret;
|
1451
1577
|
}"
|
1452
1578
|
|
@@ -1676,9 +1802,9 @@ module FastRuby
|
|
1676
1802
|
|
1677
1803
|
else # else recvtype
|
1678
1804
|
if argnum == 0
|
1679
|
-
protected_block("rb_funcall(#{to_c recv}, #{intern_num tree[2]}, 0)",
|
1805
|
+
protected_block("rb_funcall(#{to_c recv}, #{intern_num tree[2]}, 0)", true, repass_var)
|
1680
1806
|
else
|
1681
|
-
protected_block("rb_funcall(#{to_c recv}, #{intern_num tree[2]}, #{argnum}, #{strargs} )",
|
1807
|
+
protected_block("rb_funcall(#{to_c recv}, #{intern_num tree[2]}, #{argnum}, #{strargs} )", true, repass_var)
|
1682
1808
|
end
|
1683
1809
|
end # if recvtype
|
1684
1810
|
end
|
@@ -1718,6 +1844,7 @@ module FastRuby
|
|
1718
1844
|
VALUE block_function_address;
|
1719
1845
|
VALUE block_function_param;
|
1720
1846
|
VALUE call_frame;
|
1847
|
+
VALUE active;
|
1721
1848
|
#{@locals.map{|l| "VALUE #{l};\n"}.join}
|
1722
1849
|
}"
|
1723
1850
|
|
@@ -1777,6 +1904,7 @@ module FastRuby
|
|
1777
1904
|
plocals = (typeof(plocals))stack_chunk_alloc(frame.stack_chunk ,sizeof(typeof(*plocals))/sizeof(void*));
|
1778
1905
|
|
1779
1906
|
frame.plocals = plocals;
|
1907
|
+
plocals->active = Qtrue;
|
1780
1908
|
plocals->self = self;
|
1781
1909
|
plocals->call_frame = LONG2FIX(0);
|
1782
1910
|
|
@@ -1789,6 +1917,7 @@ module FastRuby
|
|
1789
1917
|
stack_chunk_reference_assign(stack_chunk_reference, rb_previous_stack_chunk);
|
1790
1918
|
}
|
1791
1919
|
|
1920
|
+
plocals->active = Qfalse;
|
1792
1921
|
return Qnil;
|
1793
1922
|
}
|
1794
1923
|
"
|
data/lib/fastruby.rb
CHANGED
@@ -33,6 +33,6 @@ module FastRuby
|
|
33
33
|
FastRuby.fastruby_script_path = File.expand_path(__FILE__)
|
34
34
|
FastRuby.fastruby_load_path = File.expand_path(File.dirname(__FILE__))
|
35
35
|
|
36
|
-
VERSION = "0.0.
|
36
|
+
VERSION = "0.0.9" unless defined? FastRuby::VERSION
|
37
37
|
end
|
38
38
|
|
data/spec/block/lambda_spec.rb
CHANGED
@@ -178,4 +178,24 @@ describe FastRuby, "fastruby" do
|
|
178
178
|
end
|
179
179
|
|
180
180
|
|
181
|
+
class ::LL8
|
182
|
+
|
183
|
+
alias alt_lambda lambda
|
184
|
+
|
185
|
+
fastruby "
|
186
|
+
def foo
|
187
|
+
lambda_obj = alt_lambda {
|
188
|
+
return 9
|
189
|
+
}
|
190
|
+
|
191
|
+
lambda_obj.call
|
192
|
+
end
|
193
|
+
"
|
194
|
+
end
|
195
|
+
|
196
|
+
it "should close lambda with return when renamed with alias" do
|
197
|
+
ll8 = ::LL8.new
|
198
|
+
ll8.foo.should be == 9
|
199
|
+
end
|
200
|
+
|
181
201
|
end
|
@@ -0,0 +1,248 @@
|
|
1
|
+
require "fastruby"
|
2
|
+
|
3
|
+
describe FastRuby, "fastruby" do
|
4
|
+
class ::LN1
|
5
|
+
fastruby "
|
6
|
+
def foo
|
7
|
+
a = 16
|
8
|
+
proc {|x|
|
9
|
+
a+x
|
10
|
+
}
|
11
|
+
end
|
12
|
+
"
|
13
|
+
end
|
14
|
+
|
15
|
+
it "proc must be able to access local variables" do
|
16
|
+
::LN1.new.foo.call(16).should be == 32
|
17
|
+
end
|
18
|
+
|
19
|
+
fastruby "
|
20
|
+
class ::LN2
|
21
|
+
def foo
|
22
|
+
a = 16
|
23
|
+
proc {|x|
|
24
|
+
a+x
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
def bar
|
29
|
+
end
|
30
|
+
end
|
31
|
+
"
|
32
|
+
|
33
|
+
it "proc must be able to access local variables, after another unrelated method is called" do
|
34
|
+
ll2 = ::LN2.new
|
35
|
+
proc_object = ll2.foo
|
36
|
+
::LN2.new.bar
|
37
|
+
proc_object.call(16).should be == 32
|
38
|
+
end
|
39
|
+
|
40
|
+
fastruby "
|
41
|
+
class ::LN3
|
42
|
+
def foo(a)
|
43
|
+
proc {|x|
|
44
|
+
a+x
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
def bar(y)
|
49
|
+
proc_object = foo(16)
|
50
|
+
foo(160)
|
51
|
+
proc_object.call(y)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
"
|
55
|
+
|
56
|
+
it "proc must be able to access local variables, after another unrelated method is called (from fastruby)" do
|
57
|
+
ll3 = ::LN3.new
|
58
|
+
ll3.bar(1).should be == 17
|
59
|
+
end
|
60
|
+
|
61
|
+
fastruby "
|
62
|
+
class ::LN4
|
63
|
+
def foo
|
64
|
+
proc {|x|
|
65
|
+
yield(x)
|
66
|
+
}
|
67
|
+
end
|
68
|
+
|
69
|
+
def bar
|
70
|
+
z = 99
|
71
|
+
foo do |x|
|
72
|
+
x+z
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def xt
|
77
|
+
proc_object = bar()
|
78
|
+
proc_object.call(1)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
"
|
82
|
+
|
83
|
+
it "proc must be able to access local variables of parent scopes through yield (from fastruby)" do
|
84
|
+
ll4 = ::LN4.new
|
85
|
+
ll4.xt.should be == 100
|
86
|
+
end
|
87
|
+
|
88
|
+
it "proc must be able to access local variables of parent scopes through yield" do
|
89
|
+
ll4 = ::LN4.new
|
90
|
+
proc_object = ll4.bar
|
91
|
+
proc_object.call(1).should be == 100
|
92
|
+
end
|
93
|
+
|
94
|
+
it "proc must be able to access local variables of parent scopes through yield on ruby" do
|
95
|
+
ll4 = ::LN4.new
|
96
|
+
|
97
|
+
a = 99
|
98
|
+
|
99
|
+
proc_object = ll4.foo do |x|
|
100
|
+
x+a
|
101
|
+
end
|
102
|
+
proc_object.call(1).should be == 100
|
103
|
+
end
|
104
|
+
|
105
|
+
def self.next_sentence(sname)
|
106
|
+
fastruby "
|
107
|
+
class ::LN5#{sname}
|
108
|
+
def foo
|
109
|
+
proc {
|
110
|
+
#{sname} 100
|
111
|
+
}
|
112
|
+
end
|
113
|
+
end
|
114
|
+
"
|
115
|
+
|
116
|
+
it "proc #{sname}'s must act as block next" do
|
117
|
+
eval("LN5"+sname).new.foo.call.should be == 100
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
next_sentence("next")
|
122
|
+
next_sentence("break")
|
123
|
+
next_sentence("return")
|
124
|
+
|
125
|
+
def self.illegal_jump(sname)
|
126
|
+
fastruby "
|
127
|
+
class ::LN6#{sname}
|
128
|
+
def foo
|
129
|
+
proc {
|
130
|
+
yield
|
131
|
+
}
|
132
|
+
end
|
133
|
+
|
134
|
+
def bar
|
135
|
+
foo do
|
136
|
+
#{sname} 9
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
"
|
141
|
+
|
142
|
+
it "#{sname} inside block should raise LocalJumpError" do
|
143
|
+
ll6 = eval("::LN6"+sname).new
|
144
|
+
lambda {
|
145
|
+
ll6.bar.call
|
146
|
+
}.should raise_error(LocalJumpError)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
illegal_jump("return")
|
151
|
+
illegal_jump("break")
|
152
|
+
|
153
|
+
|
154
|
+
fastruby "
|
155
|
+
class ::LN7
|
156
|
+
|
157
|
+
def bar(l)
|
158
|
+
l.call
|
159
|
+
yield
|
160
|
+
end
|
161
|
+
|
162
|
+
def foo
|
163
|
+
lambda_obj = proc {
|
164
|
+
}
|
165
|
+
|
166
|
+
bar(lambda_obj) do
|
167
|
+
break 0
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
"
|
172
|
+
|
173
|
+
it "should break from block after calling lambda" do
|
174
|
+
ll7 = ::LN7.new
|
175
|
+
lambda {
|
176
|
+
ll7.foo.should be == 0
|
177
|
+
}.should_not raise_error
|
178
|
+
end
|
179
|
+
|
180
|
+
fastruby "
|
181
|
+
class LN9
|
182
|
+
def foo
|
183
|
+
f = Proc.new { return 'return from foo from inside proc' }
|
184
|
+
f.call
|
185
|
+
return 'return from foo'
|
186
|
+
end
|
187
|
+
end
|
188
|
+
"
|
189
|
+
|
190
|
+
it "should return from proc using Proc.new" do
|
191
|
+
ll9 = ::LN9.new
|
192
|
+
lambda {
|
193
|
+
ll9.foo.should be == 'return from foo from inside proc'
|
194
|
+
}.should_not raise_error
|
195
|
+
end
|
196
|
+
|
197
|
+
fastruby "
|
198
|
+
class LN10
|
199
|
+
def foo
|
200
|
+
f = Proc.new { return 'return from foo from inside proc' }
|
201
|
+
f
|
202
|
+
end
|
203
|
+
end
|
204
|
+
"
|
205
|
+
|
206
|
+
it "should raise invalid return from proc using Proc.new" do
|
207
|
+
ll10 = ::LN10.new
|
208
|
+
f = ll10.foo
|
209
|
+
|
210
|
+
lambda {
|
211
|
+
f.call
|
212
|
+
}.should raise_error(LocalJumpError)
|
213
|
+
end
|
214
|
+
|
215
|
+
fastruby "
|
216
|
+
class LN11
|
217
|
+
def foo
|
218
|
+
f = Proc.new { 9 }
|
219
|
+
f.call
|
220
|
+
end
|
221
|
+
end
|
222
|
+
"
|
223
|
+
|
224
|
+
it "should call proc defined using Proc.new" do
|
225
|
+
ll11 = ::LN11.new
|
226
|
+
lambda {
|
227
|
+
ll11.foo.should be == 9
|
228
|
+
}.should_not raise_error
|
229
|
+
end
|
230
|
+
|
231
|
+
|
232
|
+
fastruby "
|
233
|
+
class LN12
|
234
|
+
def foo
|
235
|
+
f = Proc.new { break }
|
236
|
+
f.call
|
237
|
+
end
|
238
|
+
end
|
239
|
+
"
|
240
|
+
|
241
|
+
it "should raise LocalJumpError from proc using Proc.new when break is used" do
|
242
|
+
ll12 = ::LN12.new
|
243
|
+
lambda {
|
244
|
+
ll12.foo
|
245
|
+
}.should raise_error(LocalJumpError)
|
246
|
+
end
|
247
|
+
|
248
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fastruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 13
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 9
|
10
|
+
version: 0.0.9
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Dario Seminara
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-09-
|
18
|
+
date: 2011-09-28 00:00:00 -03:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -94,6 +94,7 @@ files:
|
|
94
94
|
- spec/block/next_spec.rb
|
95
95
|
- spec/block/break_spec.rb
|
96
96
|
- spec/block/callcc_spec.rb
|
97
|
+
- spec/block/proc_spec.rb
|
97
98
|
- spec/block_spec.rb
|
98
99
|
- spec/flow_control/case_spec.rb
|
99
100
|
- spec/sugar_spec.rb
|