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