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