mirah 0.1.1-java → 0.1.2-java
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.
- checksums.yaml +7 -0
- data/History.txt +133 -0
- data/Rakefile +78 -27
- data/javalib/mirah-bootstrap.jar +0 -0
- data/javalib/mirah-builtins.jar +0 -0
- data/javalib/mirah-compiler.jar +0 -0
- data/javalib/mirah-mirrors.jar +0 -0
- data/javalib/mirah-util.jar +0 -0
- data/lib/mirah/ast/scope.rb +4 -2
- data/lib/mirah/commands/run.rb +25 -20
- data/lib/mirah/env.rb +6 -0
- data/lib/mirah/errors.rb +4 -0
- data/lib/mirah/generator.rb +28 -7
- data/lib/mirah/jvm/compiler/jvm_bytecode.rb +1 -1
- data/lib/mirah/jvm/types/factory.rb +4 -10
- data/lib/mirah/util/argument_processor.rb +4 -0
- data/lib/mirah/version.rb +1 -1
- data/test/core/typer/assignable_type_future_test.rb +73 -0
- data/test/core/typer/error_type_test.rb +61 -0
- data/test/core/typer/simple_type_test.rb +69 -0
- data/test/jvm/blocks_test.rb +263 -3
- data/test/jvm/bytecode_test_helper.rb +17 -10
- data/test/jvm/jvm_commands_test.rb +10 -0
- data/test/jvm/string_builder_extensions_test.rb +49 -0
- data/test/jvm/{string_test.rb → string_extensions_test.rb} +32 -1
- data/test/mirrors/method_lookup_test.rb +2 -2
- data/test/mirrors/mirrors_test.rb +44 -7
- data/test/test_helper.rb +6 -0
- metadata +13 -19
- data/lib/mirah/jvm/types/methods.rb~ +0 -973
- data/lib/mirah/util/argument_processor.rb~ +0 -146
data/lib/mirah/env.rb
CHANGED
data/lib/mirah/errors.rb
CHANGED
data/lib/mirah/generator.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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(
|
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
|
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
|
data/lib/mirah/version.rb
CHANGED
@@ -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
|
data/test/jvm/blocks_test.rb
CHANGED
@@ -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
|
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
|