mirah 0.1.1-java → 0.1.2-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -42,5 +42,11 @@ module Mirah
42
42
  end
43
43
  result
44
44
  end
45
+
46
+ def self.make_urls classpath
47
+ decode_paths(classpath).map do |filename|
48
+ java.io.File.new(filename).to_uri.to_url
49
+ end.to_java(java.net.URL)
50
+ end
45
51
  end
46
52
  end
@@ -22,6 +22,10 @@ module Mirah
22
22
  super(message)
23
23
  @position = position
24
24
  end
25
+
26
+ def inspect
27
+ "MirahError: #{message} #{position}"
28
+ end
25
29
  end
26
30
 
27
31
  class NodeError < MirahError
@@ -62,7 +62,7 @@ module Mirah
62
62
  # enter all ASTs into inference engine
63
63
  puts "Inferring types..." if logging
64
64
  scoper, typer = infer_asts(top_nodes)
65
-
65
+ do_transforms top_nodes
66
66
  # compile each AST in turn
67
67
  compiler_results = compiler.compile_asts(top_nodes, scoper, typer)
68
68
 
@@ -71,8 +71,25 @@ module Mirah
71
71
  compiler_results
72
72
  end
73
73
 
74
+ def do_transforms nodes
75
+ log("Starting Transform")
76
+
77
+ java_import 'org.mirah.jvm.compiler.ClosureTransformer' rescue puts $!
78
+ java_import 'org.mirah.util.Context' rescue puts $!
79
+ #java_import 'org.mirah.typer.Typer'
80
+ #java_import 'org.mirah.macros.Compiler'
81
+ transformer = ClosureTransformer.new(Context.new.tap{|c|c.add(Java::org.mirah.typer::Typer, @typer) }) rescue nil
82
+ if transformer
83
+ nodes.each{|n| n.accept transformer, nil } # rescue log("transformer exception", $!.cause)
84
+ log("POST Transform")
85
+ log_types nodes
86
+ else
87
+ log "No transformer, skipping"
88
+ end
89
+ end
90
+
74
91
  def infer_asts(nodes, should_raise=false)
75
- begin
92
+ log_and_reraise "Caught exception during type inference" do
76
93
  nodes.each {|ast| @typer.infer(ast, false) }
77
94
  if should_raise
78
95
  error_handler = lambda do |errors|
@@ -81,13 +98,17 @@ module Mirah
81
98
  end
82
99
  end
83
100
  process_inference_errors(@typer, nodes, &error_handler)
84
- rescue NativeException => ex
85
- log("Caught exception during type inference", ex.cause)
86
- raise ex
87
- ensure
88
- log_types(nodes)
89
101
  end
90
102
  [@scoper, @typer]
103
+ ensure
104
+ log_types(nodes)
105
+ end
106
+
107
+ def log_and_reraise message
108
+ yield
109
+ rescue NativeException => ex
110
+ log(message, ex.cause)
111
+ raise ex
91
112
  end
92
113
 
93
114
  def log_types(nodes)
@@ -127,7 +127,7 @@ module Mirah
127
127
  param_type = inferred_type(param)
128
128
  if scope.captured?(param.name.identifier)
129
129
  @method.dup
130
- type.load(@method, @method.local(name, param_type))
130
+ param_type.load(@method, @method.local(name, param_type))
131
131
  @method.putfield(type, name, param_type)
132
132
  end
133
133
  end
@@ -712,15 +712,9 @@ module Mirah::JVM::Types
712
712
  end
713
713
  end
714
714
 
715
- def make_urls(classpath)
716
- Mirah::Env.decode_paths(classpath).map do |filename|
717
- java.io.File.new(filename).to_uri.to_url
718
- end.to_java(java.net.URL)
719
- end
720
-
721
715
  def base_classpath
722
716
  if __FILE__.include? '.jar'
723
- Mirah::Env.encode_paths([__FILE__.split('!').first.split(':').last])
717
+ Mirah::Env.encode_paths([__FILE__.split('!').first.split(Mirah::Env.path_separator).last])
724
718
  else
725
719
  Mirah::Env.encode_paths(['.',
726
720
  File.dirname(__FILE__) + '/../../../../javalib/mirah-builtins.jar',
@@ -735,19 +729,19 @@ module Mirah::JVM::Types
735
729
 
736
730
  def classpath=(classpath)
737
731
  if classpath
738
- @classpath = classpath + ":" + base_classpath
732
+ @classpath = Mirah::Env.encode_paths [classpath, base_classpath]
739
733
  end
740
734
  @resource_loader = nil
741
735
  end
742
736
 
743
737
  def resource_loader
744
- @resource_loader ||= URLClassLoader.new(make_urls(classpath), bootstrap_loader)
738
+ @resource_loader ||= URLClassLoader.new(Mirah::Env.make_urls(classpath), bootstrap_loader)
745
739
  end
746
740
 
747
741
  def bootstrap_loader
748
742
  @bootstrap_loader ||= begin
749
743
  parent = if bootclasspath
750
- Mirah::Util::IsolatedResourceLoader.new(make_urls(bootclasspath))
744
+ Mirah::Util::IsolatedResourceLoader.new(Mirah::Env.make_urls(bootclasspath))
751
745
  end
752
746
  if __FILE__ =~ /^(file:.+jar)!/
753
747
  bootstrap_urls = [java.net.URL.new($1)].to_java(java.net.URL)
@@ -131,6 +131,10 @@ module Mirah
131
131
  -I DIR\t\tAdd DIR to the Ruby load path before running
132
132
  --jvm VERSION\t\tEmit JVM bytecode targeting specified JVM
133
133
  \t\t\t version (1.4, 1.5, 1.6, 1.7)
134
+ --no-save-extensions\tDon't write macro classes to files
135
+ --no-color\t\tDon't use color when writing logs
136
+ -N, --new-backend\tUse the new backend
137
+ -T, --new-types\tUse the new type system
134
138
  -p, --plugin PLUGIN\trequire 'mirah/plugin/PLUGIN' before running
135
139
  -v, --version\t\tPrint the version of Mirah to the console
136
140
  -V, --verbose\t\tVerbose logging
@@ -14,5 +14,5 @@
14
14
  # limitations under the License.
15
15
 
16
16
  module Mirah
17
- VERSION = "0.1.1"
17
+ VERSION = "0.1.2"
18
18
  end
@@ -0,0 +1,73 @@
1
+ # Copyright (c) 2013 The Mirah project authors. All Rights Reserved.
2
+ # All contributing project authors may be found in the NOTICE file.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ require 'test_helper'
16
+
17
+ class TypeFutureTest < Test::Unit::TestCase
18
+ include Mirah
19
+ include Mirah::Util::ProcessErrors
20
+ java_import 'org.mirah.typer.TypeFuture'
21
+ java_import 'org.mirah.typer.AssignableTypeFuture'
22
+ java_import 'org.mirah.typer.SimpleFuture'
23
+ java_import 'org.mirah.typer.simple.SimpleScoper'
24
+ java_import 'org.mirah.typer.simple.SimpleTypes'
25
+ java_import 'org.mirah.typer.simple.SimpleType'
26
+ java_import 'org.mirah.typer.ErrorType'
27
+ java_import 'mirah.lang.ast.VCall'
28
+ java_import 'mirah.lang.ast.FunctionalCall'
29
+ java_import 'mirah.lang.ast.PositionImpl'
30
+ java_import 'mirah.lang.ast.LocalAccess'
31
+
32
+ module TypeFuture
33
+ def inspect
34
+ toString
35
+ end
36
+ end
37
+
38
+ POS = PositionImpl.new(nil, 0, 0, 0, 0, 0, 0)
39
+
40
+ # error type test
41
+
42
+ # END error type test
43
+
44
+ def test_assignable_future_when_declared_resolves_to_declared_type
45
+ future = AssignableTypeFuture.new POS
46
+ type = SimpleType.new("Object",false,false)
47
+ future.declare SimpleFuture.new(type), POS
48
+
49
+ assert_equal type, future.resolve, "Expected #{future.resolve} to be a #{type}"
50
+ end
51
+
52
+
53
+ def test_assignable_future_doesnt_allow_multiple_declarations_of_different_types
54
+ future = AssignableTypeFuture.new POS
55
+ future.declare SimpleFuture.new(SimpleType.new("Object",false,false)), POS
56
+ future.declare SimpleFuture.new(SimpleType.new("NotObject",false,false)), POS
57
+
58
+ assign_future = future.assign SimpleFuture.new(SimpleType.new("Object",false,false)), POS
59
+
60
+ assert_kind_of ErrorType, assign_future.resolve
61
+ end
62
+
63
+ def test_assignable_future_doesnt_allow_invalid_assignment_to_declared_type
64
+ future = AssignableTypeFuture.new POS
65
+ f = SimpleFuture.new(SimpleType.new("Object",false,false))
66
+
67
+ future.declare f, POS
68
+
69
+ assignment_future = future.assign SimpleFuture.new(SimpleType.new("NotObject",false,false)), POS
70
+
71
+ assert_kind_of ErrorType, assignment_future.resolve
72
+ end
73
+ end
@@ -0,0 +1,61 @@
1
+ # Copyright (c) 2013 The Mirah project authors. All Rights Reserved.
2
+ # All contributing project authors may be found in the NOTICE file.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ require 'test_helper'
16
+
17
+ class ErrorTypeTest < Test::Unit::TestCase
18
+ include Mirah
19
+ include Mirah::Util::ProcessErrors
20
+ java_import 'org.mirah.typer.TypeFuture'
21
+ java_import 'org.mirah.typer.AssignableTypeFuture'
22
+ java_import 'org.mirah.typer.SimpleFuture'
23
+ java_import 'org.mirah.typer.simple.SimpleScoper'
24
+ java_import 'org.mirah.typer.simple.SimpleTypes'
25
+ java_import 'org.mirah.typer.simple.SimpleType'
26
+ java_import 'org.mirah.typer.ErrorType'
27
+ java_import 'mirah.lang.ast.VCall'
28
+ java_import 'mirah.lang.ast.FunctionalCall'
29
+ java_import 'mirah.lang.ast.PositionImpl'
30
+ java_import 'mirah.lang.ast.LocalAccess'
31
+
32
+ module TypeFuture
33
+ def inspect
34
+ toString
35
+ end
36
+ end
37
+
38
+ POS = PositionImpl.new(nil, 0, 0, 0, 0, 0, 0)
39
+
40
+ def test_error_type_matches_anything
41
+ type = ErrorType.new [["",POS]]
42
+ assert type.matchesAnything, "errors match any type"
43
+ end
44
+
45
+ def test_error_type_is_not_assignable_from
46
+ type = ErrorType.new [["",POS]]
47
+ assert !type.assignableFrom(SimpleType.new("Object",false,false))
48
+ end
49
+
50
+ def test_error_type_equal_to_another_error_type_when_message_same
51
+ type = ErrorType.new [["message one",POS]]
52
+ type2 = ErrorType.new [["message one",POS]]
53
+ assert_equal type, type2
54
+ end
55
+
56
+ def test_error_type_not_equal_to_another_error_type_when_message_differs
57
+ type = ErrorType.new [["message one",POS]]
58
+ type2 = ErrorType.new [["message two",POS]]
59
+ assert_not_equal type, type2
60
+ end
61
+ end
@@ -0,0 +1,69 @@
1
+ # Copyright (c) 2013 The Mirah project authors. All Rights Reserved.
2
+ # All contributing project authors may be found in the NOTICE file.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ require 'test_helper'
16
+
17
+ class SimpleTypeTest < Test::Unit::TestCase
18
+ include Mirah
19
+ include Mirah::Util::ProcessErrors
20
+ java_import 'org.mirah.typer.TypeFuture'
21
+ java_import 'org.mirah.typer.AssignableTypeFuture'
22
+ java_import 'org.mirah.typer.SimpleFuture'
23
+ java_import 'org.mirah.typer.simple.SimpleScoper'
24
+ java_import 'org.mirah.typer.simple.SimpleTypes'
25
+ java_import 'org.mirah.typer.simple.SimpleType'
26
+ java_import 'org.mirah.typer.ErrorType'
27
+ java_import 'mirah.lang.ast.VCall'
28
+ java_import 'mirah.lang.ast.FunctionalCall'
29
+ java_import 'mirah.lang.ast.PositionImpl'
30
+ java_import 'mirah.lang.ast.LocalAccess'
31
+
32
+ module TypeFuture
33
+ def inspect
34
+ toString
35
+ end
36
+ end
37
+
38
+ POS = PositionImpl.new(nil, 0, 0, 0, 0, 0, 0)
39
+
40
+ def test_simple_type_widens_to_simple_type_of_same_name
41
+ type = SimpleType.new("Object",false,false)
42
+ assert_equal type, type.widen(SimpleType.new("Object",false,false))
43
+ end
44
+
45
+ def test_simple_type_equals_simple_type_of_same_name
46
+ type = SimpleType.new("Object",false,false)
47
+ assert_equal type, SimpleType.new("Object",false,false)
48
+ end
49
+
50
+ def test_simple_type_assignable_from_type_of_same_name
51
+ type = SimpleType.new("Object",false,false)
52
+ assert type.assignableFrom SimpleType.new("Object",false,false)
53
+ end
54
+
55
+ def test_simple_type_widens_to_error_type_when_other_has_different_name
56
+ type = SimpleType.new("Object",false,false)
57
+ assert_kind_of ErrorType, type.widen(SimpleType.new("NotObject",false,false))
58
+ end
59
+
60
+ def test_simple_type_does_not_equal_simple_type_of_different_name
61
+ type = SimpleType.new("Object",false,false)
62
+ assert_not_equal type, SimpleType.new("NotObject",false,false)
63
+ end
64
+
65
+ def test_simple_type_not_assignable_from_type_of_different_name
66
+ type = SimpleType.new("Object",false,false)
67
+ assert !type.assignableFrom(SimpleType.new("NotObject",false,false))
68
+ end
69
+ end
@@ -58,7 +58,6 @@ class BlocksTest < Test::Unit::TestCase
58
58
  end
59
59
  end
60
60
 
61
-
62
61
  def test_simple_block
63
62
  cls, = compile(<<-EOF)
64
63
  thread = Thread.new do
@@ -130,6 +129,20 @@ class BlocksTest < Test::Unit::TestCase
130
129
  assert_equal(2, cls.foo)
131
130
  end
132
131
 
132
+
133
+ def test_int_closure_with_int_as_method_param
134
+ cls, = compile(<<-EOF)
135
+ def run(x:Runnable)
136
+ x.run
137
+ end
138
+ def foo a: int
139
+ run {a += 1}
140
+ a
141
+ end
142
+ EOF
143
+ assert_equal(2, cls.foo(1))
144
+ end
145
+
133
146
  def test_block_with_method_def
134
147
  cls, = compile(<<-EOF)
135
148
  import java.util.ArrayList
@@ -333,7 +346,7 @@ class BlocksTest < Test::Unit::TestCase
333
346
  end
334
347
  end
335
348
 
336
- def test_block_with_interface_method_with_2_arguments
349
+ def test_block_with_interface_method_with_2_arguments_with_types
337
350
  cls, = compile(<<-EOF)
338
351
  interface DoubleArgMethod do
339
352
  def run(a: String, b: int):void;end
@@ -344,7 +357,7 @@ class BlocksTest < Test::Unit::TestCase
344
357
  a.run "hello", 1243
345
358
  end
346
359
  end
347
- ExpectsDoubleArgMethod.new.foo do |a, b|
360
+ ExpectsDoubleArgMethod.new.foo do |a: String, b: int|
348
361
  puts a
349
362
  puts b
350
363
  end
@@ -353,4 +366,251 @@ class BlocksTest < Test::Unit::TestCase
353
366
  cls.main(nil)
354
367
  end
355
368
  end
369
+
370
+ def test_block_with_interface_method_with_2_arguments_without_types
371
+ cls, = compile(<<-EOF)
372
+ interface DoubleArgMethod2 do
373
+ def run(a: String, b: int):void;end
374
+ end
375
+
376
+ class ExpectsDoubleArgMethod2
377
+ def foo(a:DoubleArgMethod2)
378
+ a.run "hello", 1243
379
+ end
380
+ end
381
+ ExpectsDoubleArgMethod2.new.foo do |a, b|
382
+ puts a
383
+ puts b
384
+ end
385
+ EOF
386
+ assert_output "hello\n1243\n" do
387
+ cls.main(nil)
388
+ end
389
+ end
390
+
391
+
392
+ def test_closures_support_non_local_return
393
+ pend "nlr doesnt work right now" do
394
+ cls, = compile(<<-EOF)
395
+ class NonLocalMe
396
+ def foo(a: Runnable)
397
+ a.run
398
+ puts "doesn't get here"
399
+ end
400
+ end
401
+ def nlr: String
402
+ NonLocalMe.new.foo { return "NLR!"}
403
+ "nor here either"
404
+ end
405
+ puts nlr
406
+ EOF
407
+ assert_output "NLR!\n" do
408
+ cls.main(nil)
409
+ end
410
+ end
411
+ end
412
+
413
+ def test_closures_support_non_local_return_with_primitives
414
+ pend "nlr doesnt work right now" do
415
+ cls, = compile(<<-EOF)
416
+ class NonLocalMe
417
+ def foo(a: Runnable)
418
+ a.run
419
+ puts "doesn't get here"
420
+ end
421
+ end
422
+ def nlr: int
423
+ NonLocalMe.new.foo { return 1234}
424
+ 5678
425
+ end
426
+ puts nlr
427
+ EOF
428
+ assert_output "1234\n" do
429
+ cls.main(nil)
430
+ end
431
+ end
432
+ end
433
+
434
+ def test_when_non_local_return_types_incompatible_has_error
435
+ pend "nlr doesnt work right now" do
436
+ error = assert_raises Mirah::MirahError do
437
+ parse_and_type(<<-CODE)
438
+ class NonLocalMe
439
+ def foo(a: Runnable)
440
+ a.run
441
+ puts "doesn't get here"
442
+ end
443
+ end
444
+ def nlr: int
445
+ NonLocalMe.new.foo { return "not an int"}
446
+ 5678
447
+ end
448
+
449
+ CODE
450
+ end
451
+ assert error.message.include? 'int'
452
+ end
453
+ end
454
+
455
+ def test_closures_non_local_return_to_a_script
456
+ pend "nlr doesnt work right now" do
457
+ cls, = compile(<<-EOF)
458
+ def foo(a: Runnable)
459
+ a.run
460
+ puts "doesn't get here"
461
+ end
462
+ puts "before"
463
+ foo { return }
464
+ puts "or here"
465
+ EOF
466
+ assert_output "before\n" do
467
+ cls.main(nil)
468
+ end
469
+ end
470
+ end
471
+
472
+ def test_closures_non_local_return_defined_in_a_class
473
+ pend "nlr doesnt work right now" do
474
+ cls, = compile(<<-EOF)
475
+ class ClosureInMethodInClass
476
+ def foo(a: Runnable)
477
+ a.run
478
+ puts "doesn't get here"
479
+ end
480
+ def nlr
481
+ puts "before"
482
+ foo { return 1234 }
483
+ puts "or here"
484
+ 5678
485
+ end
486
+ end
487
+ puts ClosureInMethodInClass.new.nlr
488
+ EOF
489
+ assert_output "before\n1234\n" do
490
+ cls.main(nil)
491
+ end
492
+ end
493
+ end
494
+
495
+ def test_closures_non_local_return_defined_in_a_void_method
496
+ pend "nlr doesnt work right now" do
497
+ cls, = compile(<<-EOF)
498
+ class ClosureInVoidMethodInClass
499
+ def foo(a: Runnable)
500
+ a.run
501
+ puts "doesn't get here"
502
+ end
503
+ def nlr: void
504
+ puts "before"
505
+ foo { return }
506
+ puts "or here"
507
+ end
508
+ end
509
+ ClosureInVoidMethodInClass.new.nlr
510
+ EOF
511
+ puts "before running"
512
+ assert_output "before\n" do
513
+ cls.main(nil)
514
+ end
515
+ end
516
+ end
517
+
518
+ def test_closure_non_local_return_with_multiple_returns
519
+ pend "nlr doesnt work right now" do
520
+ cls, = compile(<<-EOF)
521
+ class NLRMultipleReturnRunner
522
+ def foo(a: Runnable)
523
+ a.run
524
+ puts "doesn't get here"
525
+ end
526
+ end
527
+ def nlr(flag: boolean): String
528
+ NLRMultipleReturnRunner.new.foo { if flag; return "NLR!"; else; return "NLArrrr"; end}
529
+ "nor here either"
530
+ end
531
+ puts nlr true
532
+ puts nlr false
533
+ EOF
534
+ assert_output "NLR!\nNLArrrr\n" do
535
+ cls.main(nil)
536
+ end
537
+ end
538
+ end
539
+
540
+ def test_two_nlr_closures_in_the_same_method_in_if
541
+ pend "nlr doesnt work right now" do
542
+ cls, = compile(<<-EOF)
543
+ class NLRTwoClosure
544
+ def foo(a: Runnable)
545
+ a.run
546
+ puts "doesn't get here"
547
+ end
548
+ end
549
+ def nlr(flag: boolean): String
550
+ if flag
551
+ NLRTwoClosure.new.foo { return "NLR!" }
552
+ else
553
+ NLRTwoClosure.new.foo { return "NLArrrr" }
554
+ end
555
+ "nor here either"
556
+ end
557
+ puts nlr true
558
+ puts nlr false
559
+ EOF
560
+ assert_output "NLR!\nNLArrrr\n" do
561
+ cls.main(nil)
562
+ end
563
+ end
564
+ end
565
+
566
+ def test_two_nlr_closures_in_the_same_method
567
+ pend "nlr doesnt work right now" do
568
+ # this has a binding generation problem
569
+ cls, = compile(<<-EOF)
570
+ class NonLocalMe2
571
+ def foo(a: Runnable)
572
+ a.run
573
+ puts "may get here"
574
+ end
575
+ end
576
+ def nlr(flag: boolean): String
577
+ NonLocalMe2.new.foo { return "NLR!" if flag }
578
+ NonLocalMe2.new.foo { return "NLArrrr" unless flag }
579
+ "but not here"
580
+ end
581
+ puts nlr true
582
+ puts nlr false
583
+ EOF
584
+ assert_output "NLR!\nmay get here\nNLArrrr\n" do
585
+ cls.main(nil)
586
+ end
587
+ end
588
+ end
589
+
590
+
591
+ def test_two_closures_in_the_same_method
592
+ cls, = compile(<<-EOF)
593
+ def foo(a: Runnable)
594
+ a.run
595
+ end
596
+ def regular: String
597
+ foo { puts "Closure!" }
598
+ foo { puts "We Want it" }
599
+ "finish"
600
+ end
601
+ regular
602
+ EOF
603
+ assert_output "Closure!\nWe Want it\n" do
604
+ cls.main(nil)
605
+ end
606
+ end
607
+
608
+ # nested nlr scopes
609
+
610
+ # works with script as end
611
+ # non-local-return when return type incompat, has sensible error
612
+ # non-local-return when multiple non-local-return blocks in same method
613
+ # non-local-return when multiple non-local-return blocks in same method, in if statment
614
+ # non-local-return when multiple non-local-return block with multiple returns
615
+ #
356
616
  end