fastruby 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,7 @@
1
+ 0.0.9 Proc support
2
+
3
+ Enhanced lambda, proc and Proc.new hook by using nodes for method identification at runtime instead of method name
4
+
1
5
  0.0.8 Lambda support
2
6
 
3
7
  Re-implemented break
data/Rakefile CHANGED
@@ -7,7 +7,7 @@ require "rspec/core/rake_task"
7
7
 
8
8
  spec = Gem::Specification.new do |s|
9
9
  s.name = 'fastruby'
10
- s.version = '0.0.8'
10
+ s.version = '0.0.9'
11
11
  s.author = 'Dario Seminara'
12
12
  s.email = 'robertodarioseminara@gmail.com'
13
13
  s.platform = Gem::Platform::RUBY
@@ -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 = to_c recv_tree
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 = to_c recv_tree
352
+ str_recv = "pframe->next_recv"
343
353
  str_recv = "plocals->self" unless recv_tree
344
354
 
345
- execute_code = if mname == :lambda or mname == :proc
346
- "VALUE ret = rb_funcall(#{str_recv}, #{intern_num call_tree[2]}, 0);
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
- target_escape_code = if mname == :lambda or mname == :proc
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
- fake_frame.plocals = (void*)&fake_locals;
395
- fake_frame.parent_frame = 0;
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
- fake_locals.pframe = LONG2FIX(&fake_frame);
406
+ #{@frame_struct} frame;
407
+ #{@frame_struct} *pframe = (void*)&frame;
408
+ #{@locals_struct} *plocals = (void*)_plocals;
398
409
 
399
- VALUE old_call_frame = ((typeof(fake_locals)*)(pframe->plocals))->call_frame;
400
- ((typeof(fake_locals)*)(pframe->plocals))->call_frame = LONG2FIX(pframe);
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.parent_frame = (void*)&fake_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(fake_locals)*)(pframe->plocals))->self, #{intern_num :raise}, 1, frame.exception);
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(fake_locals)*)(pframe->plocals))->call_frame = old_call_frame;
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(fake_locals)*)(pframe->plocals))->call_frame = old_call_frame;
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
- else
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
- VALUE ex = rb_funcall(
438
- #{literal_value FastRuby::Context::UnwindFastrubyFrame},
439
- #{intern_num :new},
440
- 3,
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
- rb_funcall(plocals->self, #{intern_num :raise}, 1, ex);
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
- return frame.return_value;
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
- end
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
- #{target_escape_code}
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("rb_iterate(#{anonymous_function(&rb_funcall_caller_code)}, (VALUE)pframe, #{anonymous_function(&rb_funcall_block_code)}, (VALUE)plocals)", true)
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
- "pframe->target_frame = ((typeof(pframe))FIX2LONG(plocals->pframe)); plocals->return_value = #{to_c(tree[1])}; pframe->return_value = plocals->return_value; longjmp(pframe->jmp, 1); return Qnil;\n"
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)", false, repass_var)
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} )", false, repass_var)
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.8" unless defined? FastRuby::VERSION
36
+ VERSION = "0.0.9" unless defined? FastRuby::VERSION
37
37
  end
38
38
 
@@ -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: 15
4
+ hash: 13
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 8
10
- version: 0.0.8
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-22 00:00:00 -03:00
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