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
@@ -16,18 +16,20 @@ require 'test_helper'
|
|
16
16
|
require 'set'
|
17
17
|
|
18
18
|
module JVMCompiler
|
19
|
-
TEST_DEST = File.expand_path(File.dirname(__FILE__)+'/../../tmp_test/') + "/"
|
20
19
|
$CLASSPATH << TEST_DEST
|
21
20
|
|
22
|
-
|
23
|
-
|
21
|
+
java_import 'java.lang.System'
|
22
|
+
java_import 'java.io.PrintStream'
|
23
|
+
java_import 'java.net.URLClassLoader'
|
24
|
+
java_import 'org.jruby.javasupport.JavaClass'
|
25
|
+
|
24
26
|
include Mirah
|
25
27
|
|
26
28
|
def new_state
|
27
29
|
state = Mirah::Util::CompilationState.new
|
28
30
|
state.save_extensions = true
|
29
31
|
state.destination = TEST_DEST
|
30
|
-
state.classpath = TEST_DEST
|
32
|
+
state.classpath = Env.encode_paths [TEST_DEST, FIXTURE_TEST_DEST]
|
31
33
|
state.type_system = type_system if type_system
|
32
34
|
state
|
33
35
|
end
|
@@ -71,7 +73,7 @@ module JVMCompiler
|
|
71
73
|
ast
|
72
74
|
end
|
73
75
|
|
74
|
-
def generate_classes compiler_results
|
76
|
+
def generate_classes compiler_results, state
|
75
77
|
classes = {}
|
76
78
|
|
77
79
|
compiler_results.each do |result|
|
@@ -83,11 +85,15 @@ module JVMCompiler
|
|
83
85
|
classes[result.filename[0..-7]] = Mirah::Util::ClassLoader.binary_string bytes
|
84
86
|
end
|
85
87
|
|
86
|
-
loader = Mirah::Util::ClassLoader.new(
|
88
|
+
loader = Mirah::Util::ClassLoader.new(
|
89
|
+
URLClassLoader.new(
|
90
|
+
Mirah::Env.make_urls(state.classpath),
|
91
|
+
JRuby.runtime.jruby_class_loader),
|
92
|
+
classes)
|
87
93
|
|
88
94
|
classes.keys.map do |name|
|
89
95
|
cls = loader.load_class(name.tr('/', '.'))
|
90
|
-
JavaUtilities.get_proxy_class(cls
|
96
|
+
JavaUtilities.get_proxy_class(JavaClass.get(JRuby.runtime, cls))
|
91
97
|
end
|
92
98
|
end
|
93
99
|
|
@@ -107,9 +113,10 @@ module JVMCompiler
|
|
107
113
|
ast = [AST.parse_ruby(nil, code, name)]
|
108
114
|
|
109
115
|
scoper, typer = generator.infer_asts(ast, true)
|
116
|
+
generator.do_transforms ast
|
110
117
|
compiler_results = generator.compiler.compile_asts(ast, scoper, typer)
|
111
118
|
|
112
|
-
generate_classes compiler_results
|
119
|
+
generate_classes compiler_results, state
|
113
120
|
end
|
114
121
|
|
115
122
|
def tmp_script_name
|
@@ -119,8 +126,8 @@ end
|
|
119
126
|
|
120
127
|
|
121
128
|
module CommonAssertions
|
122
|
-
|
123
|
-
|
129
|
+
java_import 'java.lang.System'
|
130
|
+
java_import 'java.io.PrintStream'
|
124
131
|
|
125
132
|
def assert_include(value, array, message=nil)
|
126
133
|
message = build_message message, '<?> does not include <?>', array, value
|
@@ -21,4 +21,14 @@ class JVMCommandsTest < Test::Unit::TestCase
|
|
21
21
|
Mirah::Commands::Run.new(['-e','puts 1']).execute
|
22
22
|
end
|
23
23
|
end
|
24
|
+
|
25
|
+
def test_runtime_classpath_modifications
|
26
|
+
assert_output "1234\n" do
|
27
|
+
Mirah::Commands::Run.new(['-c', FIXTURE_TEST_DEST,
|
28
|
+
'-e',
|
29
|
+
'import org.foo.LowerCaseInnerClass
|
30
|
+
puts LowerCaseInnerClass.inner.field']
|
31
|
+
).execute
|
32
|
+
end
|
33
|
+
end
|
24
34
|
end
|
@@ -0,0 +1,49 @@
|
|
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
|
+
|
16
|
+
class StringBuilderExtensionsTest < Test::Unit::TestCase
|
17
|
+
def test_string_builder_greetings
|
18
|
+
result = '<p>Greetings are: hello hola ciao salut hallo</p>'
|
19
|
+
cls, = compile(<<-EOF)
|
20
|
+
def greetings
|
21
|
+
languages = ['hello ', 'hola ', 'ciao ', 'salut ', 'hallo']
|
22
|
+
greetings = StringBuilder.new
|
23
|
+
greetings << '<p>Greetings are: '
|
24
|
+
languages.each { |greet| greetings << greet }
|
25
|
+
greetings << '</p>'
|
26
|
+
greetings.toString
|
27
|
+
end
|
28
|
+
EOF
|
29
|
+
assert_equal result, cls.greetings
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_string_builder_shovel_object
|
33
|
+
cls, = compile(<<-EOF)
|
34
|
+
class MyObject
|
35
|
+
def toString
|
36
|
+
"Hey, I am a shiny instance of \#{getClass.getName}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def shovel_object
|
41
|
+
sb = StringBuilder.new
|
42
|
+
sb << MyObject.new
|
43
|
+
sb.toString
|
44
|
+
end
|
45
|
+
EOF
|
46
|
+
result = 'Hey, I am a shiny instance of MyObject'
|
47
|
+
assert_equal result, cls.shovel_object
|
48
|
+
end
|
49
|
+
end
|
@@ -13,7 +13,7 @@
|
|
13
13
|
# See the License for the specific language governing permissions and
|
14
14
|
# limitations under the License.
|
15
15
|
|
16
|
-
class
|
16
|
+
class StringExtensionsTest < Test::Unit::TestCase
|
17
17
|
|
18
18
|
def test_string_concat
|
19
19
|
cls, = compile("
|
@@ -38,4 +38,35 @@ class StringTest < Test::Unit::TestCase
|
|
38
38
|
assert_equal("a1", cls.str_long)
|
39
39
|
end
|
40
40
|
|
41
|
+
def test_string_included
|
42
|
+
cls, = compile("def included; 'abcdef'.include? 'd'; end")
|
43
|
+
assert cls.included, 'failed to find the contained string'
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_string_dont_include
|
47
|
+
cls, = compile("def dont_include; 'abcdef'.include? 'g'; end")
|
48
|
+
refute cls.dont_include, 'mistakenly found contained string'
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_string_include_wrong_type
|
52
|
+
assert_raises Mirah::MirahError do
|
53
|
+
compile("def include_wrong_type; 'abcdef'.include? 1; end")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_string_match
|
58
|
+
cls, = compile("def match; 'abcdef' =~ /d/; end")
|
59
|
+
assert cls.match, 'failed to match string'
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_string_dont_match
|
63
|
+
cls, = compile("def dont_match; 'abcdef' =~ /g/; end")
|
64
|
+
refute cls.dont_match, 'mistakenly matched string'
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_string_match_wrong_type
|
68
|
+
assert_raises Mirah::MirahError do
|
69
|
+
compile("def match_wrong_type; 'abcdef' =~ 'd'; end")
|
70
|
+
end
|
71
|
+
end
|
41
72
|
end
|
@@ -358,7 +358,7 @@ class CompareSpecificityTest < BaseMethodLookupTest
|
|
358
358
|
end
|
359
359
|
|
360
360
|
def assert_specificity(a, b, value)
|
361
|
-
actual = MethodLookup.compareSpecificity(make_method(a), make_method(b))
|
361
|
+
actual = MethodLookup.compareSpecificity(make_method(a), make_method(b), [nil, nil])
|
362
362
|
assert_block "Expected compareSpecificity(#{a.inspect}, #{b.inspect}) = #{value} but was #{actual}" do
|
363
363
|
if value.nan?
|
364
364
|
actual.nan?
|
@@ -423,7 +423,7 @@ class FindMaximallySpecificTest < BaseMethodLookupTest
|
|
423
423
|
method = make_method(m)
|
424
424
|
methods[method] = m
|
425
425
|
end
|
426
|
-
result = MethodLookup.findMaximallySpecific(methods.keys)
|
426
|
+
result = MethodLookup.findMaximallySpecific(methods.keys, [nil, nil])
|
427
427
|
result.map {|m| methods[m] || m}
|
428
428
|
end
|
429
429
|
|
@@ -21,6 +21,7 @@ class BaseMirrorsTest < Test::Unit::TestCase
|
|
21
21
|
java_import 'org.mirah.jvm.mirrors.JVMScope'
|
22
22
|
java_import 'org.mirah.jvm.types.JVMType'
|
23
23
|
java_import 'org.mirah.jvm.types.JVMTypeUtils'
|
24
|
+
java_import 'org.mirah.typer.AssignableTypeFuture'
|
24
25
|
java_import 'org.mirah.typer.BaseTypeFuture'
|
25
26
|
java_import 'org.mirah.typer.CallFuture'
|
26
27
|
java_import 'org.mirah.typer.TypeFuture'
|
@@ -45,7 +46,7 @@ class BaseMirrorsTest < Test::Unit::TestCase
|
|
45
46
|
end
|
46
47
|
|
47
48
|
def assert_descriptor(descriptor, type)
|
48
|
-
assert(type.isResolved)
|
49
|
+
assert(type.isResolved, type.resolve.toString)
|
49
50
|
assert_resolved_to(descriptor, type.resolve)
|
50
51
|
assert_not_error(type)
|
51
52
|
end
|
@@ -62,7 +63,7 @@ class BaseMirrorsTest < Test::Unit::TestCase
|
|
62
63
|
end
|
63
64
|
|
64
65
|
def assert_not_error(type)
|
65
|
-
assert(!type.resolve.isError)
|
66
|
+
assert(!type.resolve.isError, type.resolve.toString)
|
66
67
|
end
|
67
68
|
|
68
69
|
def assert_subtype_of(supertype, subtype)
|
@@ -405,6 +406,26 @@ class MTS_MethodLookupTest < BaseMirrorsTest
|
|
405
406
|
assert_resolved_to('I', type.resolve.returnType)
|
406
407
|
end
|
407
408
|
|
409
|
+
def test_async_return_type_from_superclass
|
410
|
+
a = define_type('A')
|
411
|
+
b = define_type('B', a)
|
412
|
+
type = CallFuture.new(@types, @scope, b, true, 'foo', [], [], nil)
|
413
|
+
assert_error(type)
|
414
|
+
@types.getMethodDefType(a, 'foo', [], a, nil)
|
415
|
+
assert_not_error(type)
|
416
|
+
assert_descriptor('LA;', type)
|
417
|
+
end
|
418
|
+
|
419
|
+
def test_async_return_type_from_interface
|
420
|
+
a = define_type('A')
|
421
|
+
b = define_type('B', main_type, [a])
|
422
|
+
type = CallFuture.new(@types, @scope, b, true, 'foo', [], [], nil)
|
423
|
+
assert_error(type)
|
424
|
+
@types.getMethodDefType(a, 'foo', [], a, nil)
|
425
|
+
assert_not_error(type)
|
426
|
+
assert_descriptor('LA;', type)
|
427
|
+
end
|
428
|
+
|
408
429
|
def test_infer_return_type_from_body
|
409
430
|
future = @types.getMethodDefType(main_type, 'foo', [], nil, nil)
|
410
431
|
type = @types.getMethodType(
|
@@ -420,9 +441,13 @@ class MTS_MethodLookupTest < BaseMirrorsTest
|
|
420
441
|
@scope.selfType_set(type)
|
421
442
|
int = @types.wrap(Type.getType("I"))
|
422
443
|
short = @types.wrap(Type.getType("S"))
|
423
|
-
|
444
|
+
decl = AssignableTypeFuture.new(nil)
|
445
|
+
decl.declare(int, nil)
|
446
|
+
@types.getMethodDefType(type, 'foo', [decl], int, nil)
|
424
447
|
argument_future = BaseTypeFuture.new
|
425
|
-
|
448
|
+
decl = AssignableTypeFuture.new(nil)
|
449
|
+
decl.declare(argument_future, nil)
|
450
|
+
@types.getMethodDefType(type, 'foo', [decl], short, nil)
|
426
451
|
|
427
452
|
call_future = CallFuture.new(@types, @scope, type, true, 'foo', [short], [], nil)
|
428
453
|
assert_not_error(call_future)
|
@@ -436,9 +461,13 @@ class MTS_MethodLookupTest < BaseMirrorsTest
|
|
436
461
|
def test_async_arguments_meta
|
437
462
|
int = @types.wrap(Type.getType("I"))
|
438
463
|
short = @types.wrap(Type.getType("S"))
|
439
|
-
|
464
|
+
decl = AssignableTypeFuture.new(nil)
|
465
|
+
decl.declare(int, nil)
|
466
|
+
@types.getMethodDefType(main_type, 'foo', [decl], int, nil)
|
440
467
|
argument_future = BaseTypeFuture.new
|
441
|
-
|
468
|
+
decl = AssignableTypeFuture.new(nil)
|
469
|
+
decl.declare(argument_future, nil)
|
470
|
+
@types.getMethodDefType(main_type, 'foo', [decl], short, nil)
|
442
471
|
|
443
472
|
call_future = CallFuture.new(@types, @scope, main_type, true, 'foo', [short], [], nil)
|
444
473
|
assert_not_error(call_future)
|
@@ -455,8 +484,10 @@ class MTS_MethodLookupTest < BaseMirrorsTest
|
|
455
484
|
b = @types.defineType(@scope, ClassDefinition.new, "B", super_future, [])
|
456
485
|
a = @types.defineType(@scope, ClassDefinition.new, "A", b, [])
|
457
486
|
c = @types.defineType(@scope, ClassDefinition.new, "C", nil, [])
|
487
|
+
decl = AssignableTypeFuture.new(nil)
|
488
|
+
decl.declare(c, nil)
|
458
489
|
|
459
|
-
@types.getMethodDefType(main_type, 'foobar', [
|
490
|
+
@types.getMethodDefType(main_type, 'foobar', [decl],
|
460
491
|
@types.getFixnumType(0), nil)
|
461
492
|
type1 = CallFuture.new(@types, @scope, main_type, true, 'foobar', [b], [], nil)
|
462
493
|
assert_error(type1)
|
@@ -559,4 +590,10 @@ class MTS_MethodLookupTest < BaseMirrorsTest
|
|
559
590
|
@types, @scope, collections, true, 'checkedSet', [set, klass], [], nil)
|
560
591
|
assert_equal('java.util.Set<FooBar>', checked.resolve.toString)
|
561
592
|
end
|
593
|
+
|
594
|
+
def test_nil_argument
|
595
|
+
sb = @types.get(@scope, typeref('java.lang.StringBuilder'))
|
596
|
+
result = CallFuture.new(@types, @scope, sb, true, 'append', [@types.getNullType], [], nil)
|
597
|
+
assert_descriptor('Ljava/lang/StringBuilder;', result)
|
598
|
+
end
|
562
599
|
end
|
data/test/test_helper.rb
CHANGED
@@ -19,6 +19,12 @@ require 'jruby'
|
|
19
19
|
require 'stringio'
|
20
20
|
require 'fileutils'
|
21
21
|
|
22
|
+
test_tmp_dir = File.expand_path(File.dirname(__FILE__)+'/../tmp_test/')
|
23
|
+
TEST_DEST = "#{test_tmp_dir}/test_classes/"
|
24
|
+
FIXTURE_TEST_DEST = "#{test_tmp_dir}/fixtures/"
|
25
|
+
|
26
|
+
|
27
|
+
|
22
28
|
module CommonAssertions
|
23
29
|
import java.lang.System
|
24
30
|
import java.io.PrintStream
|
metadata
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mirah
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
version: 0.1.1
|
4
|
+
version: 0.1.2
|
6
5
|
platform: java
|
7
6
|
authors:
|
8
7
|
- Charles Oliver Nutter
|
@@ -10,7 +9,7 @@ authors:
|
|
10
9
|
autorequire:
|
11
10
|
bindir: bin
|
12
11
|
cert_chain: []
|
13
|
-
date:
|
12
|
+
date: 2014-01-05 00:00:00.000000000 Z
|
14
13
|
dependencies:
|
15
14
|
- !ruby/object:Gem::Dependency
|
16
15
|
name: bitescript
|
@@ -19,13 +18,11 @@ dependencies:
|
|
19
18
|
- - '>='
|
20
19
|
- !ruby/object:Gem::Version
|
21
20
|
version: 0.1.4
|
22
|
-
none: false
|
23
21
|
requirement: !ruby/object:Gem::Requirement
|
24
22
|
requirements:
|
25
23
|
- - '>='
|
26
24
|
- !ruby/object:Gem::Version
|
27
25
|
version: 0.1.4
|
28
|
-
none: false
|
29
26
|
prerelease: false
|
30
27
|
type: :runtime
|
31
28
|
description: |-
|
@@ -93,7 +90,6 @@ files:
|
|
93
90
|
- lib/mirah/jvm/types/literals.rb
|
94
91
|
- lib/mirah/jvm/types/meta_type.rb
|
95
92
|
- lib/mirah/jvm/types/methods.rb
|
96
|
-
- lib/mirah/jvm/types/methods.rb~
|
97
93
|
- lib/mirah/jvm/types/null_type.rb
|
98
94
|
- lib/mirah/jvm/types/number.rb
|
99
95
|
- lib/mirah/jvm/types/primitive_type.rb
|
@@ -105,7 +101,6 @@ files:
|
|
105
101
|
- lib/mirah/transform/ast_ext.rb
|
106
102
|
- lib/mirah/transform/transformer.rb
|
107
103
|
- lib/mirah/util/argument_processor.rb
|
108
|
-
- lib/mirah/util/argument_processor.rb~
|
109
104
|
- lib/mirah/util/class_loader.rb
|
110
105
|
- lib/mirah/util/compilation_state.rb
|
111
106
|
- lib/mirah/util/delegate.rb
|
@@ -116,6 +111,9 @@ files:
|
|
116
111
|
- test/core/env_test.rb
|
117
112
|
- test/core/generator_test.rb
|
118
113
|
- test/core/typer_test.rb
|
114
|
+
- test/core/typer/assignable_type_future_test.rb
|
115
|
+
- test/core/typer/error_type_test.rb
|
116
|
+
- test/core/typer/simple_type_test.rb
|
119
117
|
- test/core/util/argument_processor_test.rb
|
120
118
|
- test/core/util/class_loader_test.rb
|
121
119
|
- test/core/util/compilation_state_test.rb
|
@@ -146,7 +144,8 @@ files:
|
|
146
144
|
- test/jvm/new_backend_test_helper.rb
|
147
145
|
- test/jvm/numeric_extensions_test.rb
|
148
146
|
- test/jvm/rescue_test.rb
|
149
|
-
- test/jvm/
|
147
|
+
- test/jvm/string_builder_extensions_test.rb
|
148
|
+
- test/jvm/string_extensions_test.rb
|
150
149
|
- test/jvm/varargs_test.rb
|
151
150
|
- test/mirrors/base_type_test.rb
|
152
151
|
- test/mirrors/bytecode_mirror_test.rb
|
@@ -221,6 +220,7 @@ files:
|
|
221
220
|
- javalib/mirah-bootstrap.jar
|
222
221
|
- javalib/mirah-builtins.jar
|
223
222
|
- javalib/mirah-compiler.jar
|
223
|
+
- javalib/mirah-mirrors.jar
|
224
224
|
- javalib/mirah-newast-transitional.jar
|
225
225
|
- javalib/mirah-parser.jar
|
226
226
|
- javalib/mirah-util.jar
|
@@ -228,7 +228,9 @@ files:
|
|
228
228
|
- Rakefile
|
229
229
|
- README.md
|
230
230
|
homepage: http://www.mirah.org/
|
231
|
-
licenses:
|
231
|
+
licenses:
|
232
|
+
- Apache-2.0
|
233
|
+
metadata: {}
|
232
234
|
post_install_message:
|
233
235
|
rdoc_options:
|
234
236
|
- --main
|
@@ -239,25 +241,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
239
241
|
requirements:
|
240
242
|
- - '>='
|
241
243
|
- !ruby/object:Gem::Version
|
242
|
-
segments:
|
243
|
-
- 0
|
244
|
-
hash: 2
|
245
244
|
version: '0'
|
246
|
-
none: false
|
247
245
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
248
246
|
requirements:
|
249
247
|
- - '>='
|
250
248
|
- !ruby/object:Gem::Version
|
251
|
-
segments:
|
252
|
-
- 0
|
253
|
-
hash: 2
|
254
249
|
version: '0'
|
255
|
-
none: false
|
256
250
|
requirements: []
|
257
251
|
rubyforge_project: mirah
|
258
|
-
rubygems_version: 1.
|
252
|
+
rubygems_version: 2.1.11
|
259
253
|
signing_key:
|
260
|
-
specification_version:
|
254
|
+
specification_version: 4
|
261
255
|
summary: Mirah is a customizable programming language featuring static types, local type inference and a heavily Ruby-inspired syntax
|
262
256
|
test_files:
|
263
257
|
- test/test_helper.rb
|
@@ -1,973 +0,0 @@
|
|
1
|
-
# Copyright (c) 2010-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
|
-
|
16
|
-
require 'mirah/jvm/types'
|
17
|
-
|
18
|
-
class Java::JavaMethod
|
19
|
-
def static?
|
20
|
-
java.lang.reflect.Modifier.static?(modifiers)
|
21
|
-
end
|
22
|
-
|
23
|
-
def abstract?
|
24
|
-
java.lang.reflect.Modifier.abstract?(modifiers)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
class BiteScript::ASM::FieldMirror
|
29
|
-
def returnType
|
30
|
-
self.type
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
module Mirah::JVM::Types
|
35
|
-
AST ||= Mirah::AST
|
36
|
-
|
37
|
-
module ArgumentConversion
|
38
|
-
def convert_args(compiler, values, types=nil)
|
39
|
-
# TODO boxing/unboxing
|
40
|
-
types ||= argument_types
|
41
|
-
needs_to_build_varargs_array = false
|
42
|
-
|
43
|
-
if respond_to?(:varargs?) && varargs?
|
44
|
-
non_varargs_types = types[0..-2]
|
45
|
-
non_varargs_values = values.first non_varargs_types.size
|
46
|
-
|
47
|
-
varargs_values = values.to_a.last(values.size - non_varargs_values.size)
|
48
|
-
varargs_type = types.last
|
49
|
-
|
50
|
-
unless varargs_values.length == 1 &&
|
51
|
-
varargs_type.compatible?(compiler.inferred_type(varargs_values.first))
|
52
|
-
needs_to_build_varargs_array = true
|
53
|
-
values = non_varargs_values
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
values_and_types = values.zip(types)
|
58
|
-
|
59
|
-
values_and_types.each do |value, type|
|
60
|
-
compiler.visit(value, true)
|
61
|
-
in_type = compiler.inferred_type(value)
|
62
|
-
if in_type.primitive? && type != in_type
|
63
|
-
in_type.compile_widen(compiler.method, type)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
if needs_to_build_varargs_array
|
68
|
-
compiler.visitVarargsArray(varargs_type, varargs_values)
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
Type.send :include, ArgumentConversion
|
74
|
-
|
75
|
-
class Intrinsic
|
76
|
-
include ArgumentConversion
|
77
|
-
attr_reader :name, :argument_types, :return_type
|
78
|
-
|
79
|
-
def initialize(klass, name, args, type, kind=nil, &block)
|
80
|
-
raise ArgumentError, "Block required" unless block_given?
|
81
|
-
@class = klass
|
82
|
-
@name = name
|
83
|
-
@argument_types = args
|
84
|
-
@return_type = type
|
85
|
-
@block = block
|
86
|
-
@kind = kind
|
87
|
-
end
|
88
|
-
|
89
|
-
def kind
|
90
|
-
Java::OrgMirahJvmTypes::MemberKind.const_get(@kind)
|
91
|
-
end
|
92
|
-
|
93
|
-
def accept(visitor, expression)
|
94
|
-
name = "visit_#{@kind.downcase}".sub(/_op$/,"")
|
95
|
-
visitor.send(name, self, expression)
|
96
|
-
end
|
97
|
-
|
98
|
-
def call(builder, ast, expression, *args)
|
99
|
-
@block.call(builder, ast, expression, *args)
|
100
|
-
end
|
101
|
-
|
102
|
-
def declaring_class
|
103
|
-
@class
|
104
|
-
end
|
105
|
-
|
106
|
-
def constructor?
|
107
|
-
false
|
108
|
-
end
|
109
|
-
|
110
|
-
def field?
|
111
|
-
false
|
112
|
-
end
|
113
|
-
|
114
|
-
def abstract?
|
115
|
-
false
|
116
|
-
end
|
117
|
-
|
118
|
-
def exceptions
|
119
|
-
[]
|
120
|
-
end
|
121
|
-
|
122
|
-
def varargs?
|
123
|
-
false
|
124
|
-
end
|
125
|
-
|
126
|
-
def isVararg
|
127
|
-
varargs?
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
class Macro
|
132
|
-
java_import 'org.mirah.typer.InlineCode'
|
133
|
-
java_import 'org.mirah.typer.NodeBuilder'
|
134
|
-
attr_reader :name, :argument_types, :return_type
|
135
|
-
|
136
|
-
def initialize(klass, name, args, &block)
|
137
|
-
raise ArgumentError, "Block required" unless block_given?
|
138
|
-
@class = klass
|
139
|
-
@name = name
|
140
|
-
@argument_types = args
|
141
|
-
raise ArgumentError unless args.all?
|
142
|
-
@return_type = InlineCode.new(block.to_java(NodeBuilder))
|
143
|
-
end
|
144
|
-
|
145
|
-
def declaring_class
|
146
|
-
@class
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
class JavaCallable
|
151
|
-
include ArgumentConversion
|
152
|
-
|
153
|
-
attr_accessor :member
|
154
|
-
|
155
|
-
def initialize(types, member)
|
156
|
-
raise ArgumentError unless types.kind_of?(Mirah::Typer::TypeSystem)
|
157
|
-
@types = types
|
158
|
-
@member = member
|
159
|
-
end
|
160
|
-
|
161
|
-
def name
|
162
|
-
@name ||= @member.name
|
163
|
-
end
|
164
|
-
|
165
|
-
def field?
|
166
|
-
false
|
167
|
-
end
|
168
|
-
|
169
|
-
def parameter_types
|
170
|
-
@member.parameter_types
|
171
|
-
end
|
172
|
-
|
173
|
-
def synthetic?
|
174
|
-
@member.synthetic?
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
class JavaConstructor < JavaCallable
|
179
|
-
def argument_types
|
180
|
-
@argument_types ||= @member.argument_types.map do |arg|
|
181
|
-
if arg.kind_of?(Type) || arg.nil?
|
182
|
-
arg
|
183
|
-
else
|
184
|
-
@types.type(nil, arg)
|
185
|
-
end
|
186
|
-
end
|
187
|
-
end
|
188
|
-
|
189
|
-
def return_type
|
190
|
-
declaring_class
|
191
|
-
end
|
192
|
-
|
193
|
-
def exceptions
|
194
|
-
@member.exception_types.map do |exception|
|
195
|
-
if exception.kind_of?(Mirah::Typer::ResolvedType)
|
196
|
-
exception
|
197
|
-
else
|
198
|
-
@types.type(nil, exception.class_name)
|
199
|
-
end
|
200
|
-
end
|
201
|
-
end
|
202
|
-
|
203
|
-
def declaring_class
|
204
|
-
@types.type(nil, @member.declaring_class)
|
205
|
-
end
|
206
|
-
|
207
|
-
def type_parameters
|
208
|
-
@declaring_class and @declaring_class.jvm_type.type_parameters
|
209
|
-
end
|
210
|
-
|
211
|
-
def call(compiler, ast, expression, parameters=nil, delegate=false)
|
212
|
-
target = compiler.inferred_type(ast.target)
|
213
|
-
unless delegate
|
214
|
-
compiler.method.new target
|
215
|
-
compiler.method.dup if expression
|
216
|
-
end
|
217
|
-
parameters ||= ast.parameters
|
218
|
-
convert_args(compiler, parameters)
|
219
|
-
compiler.method.invokespecial(
|
220
|
-
target,
|
221
|
-
"<init>",
|
222
|
-
[nil, *@member.argument_types])
|
223
|
-
end
|
224
|
-
|
225
|
-
def constructor?
|
226
|
-
true
|
227
|
-
end
|
228
|
-
|
229
|
-
def varargs?
|
230
|
-
@member.varargs?
|
231
|
-
end
|
232
|
-
|
233
|
-
def isVararg
|
234
|
-
varargs?
|
235
|
-
end
|
236
|
-
|
237
|
-
def accept(visitor, expression)
|
238
|
-
visitor.visitConstructor(self, expression)
|
239
|
-
end
|
240
|
-
|
241
|
-
def kind
|
242
|
-
Java::OrgMirahJvmTypes::MemberKind::CONSTRUCTOR
|
243
|
-
end
|
244
|
-
end
|
245
|
-
|
246
|
-
class JavaMethod < JavaConstructor
|
247
|
-
def return_type
|
248
|
-
@return_type ||= begin
|
249
|
-
if void?
|
250
|
-
@types.type(nil, 'void')
|
251
|
-
else
|
252
|
-
@types.type(nil, @member.return_type)
|
253
|
-
end
|
254
|
-
end
|
255
|
-
end
|
256
|
-
|
257
|
-
def static?
|
258
|
-
@member.static?
|
259
|
-
end
|
260
|
-
|
261
|
-
def abstract?
|
262
|
-
@member.abstract?
|
263
|
-
end
|
264
|
-
|
265
|
-
def type_parameters
|
266
|
-
@member.type_parameters
|
267
|
-
end
|
268
|
-
|
269
|
-
def void?
|
270
|
-
return_type = @member.return_type
|
271
|
-
return true if return_type.nil?
|
272
|
-
if return_type.respond_to?(:descriptor) && return_type.descriptor == 'V'
|
273
|
-
return true
|
274
|
-
end
|
275
|
-
false
|
276
|
-
end
|
277
|
-
|
278
|
-
def constructor?
|
279
|
-
false
|
280
|
-
end
|
281
|
-
|
282
|
-
def accept(visitor, expression)
|
283
|
-
if self.static?
|
284
|
-
visitor.visitStaticMethodCall(self, expression)
|
285
|
-
else
|
286
|
-
visitor.visitMethodCall(self, expression)
|
287
|
-
end
|
288
|
-
end
|
289
|
-
|
290
|
-
def kind
|
291
|
-
if self.static?
|
292
|
-
Java::OrgMirahJvmTypes::MemberKind::STATIC_METHOD
|
293
|
-
else
|
294
|
-
Java::OrgMirahJvmTypes::MemberKind::METHOD
|
295
|
-
end
|
296
|
-
end
|
297
|
-
|
298
|
-
def call(compiler, ast, expression, parameters=nil)
|
299
|
-
target = compiler.inferred_type(ast.target)
|
300
|
-
compiler.visit(ast.target, true)
|
301
|
-
|
302
|
-
# if expression, void methods return the called object,
|
303
|
-
# for consistency and chaining
|
304
|
-
# TODO: inference phase needs to track that signature is
|
305
|
-
# void but actual type is callee
|
306
|
-
if expression && void?
|
307
|
-
compiler.method.dup
|
308
|
-
end
|
309
|
-
|
310
|
-
parameters ||= ast.parameters
|
311
|
-
convert_args(compiler, parameters)
|
312
|
-
if target.interface?
|
313
|
-
compiler.method.invokeinterface(
|
314
|
-
target,
|
315
|
-
name,
|
316
|
-
[@member.return_type, *@member.argument_types])
|
317
|
-
else
|
318
|
-
compiler.method.invokevirtual(
|
319
|
-
target,
|
320
|
-
name,
|
321
|
-
[@member.return_type, *@member.argument_types])
|
322
|
-
end
|
323
|
-
|
324
|
-
if expression && !void?
|
325
|
-
# Insert a cast if the inferred type and actual type differ. This is part of generics support.
|
326
|
-
inferred_return_type = compiler.inferred_type(ast)
|
327
|
-
if !inferred_return_type.assignableFrom(return_type)
|
328
|
-
compiler.method.checkcast(inferred_return_type)
|
329
|
-
end
|
330
|
-
end
|
331
|
-
|
332
|
-
unless expression || void?
|
333
|
-
return_type.pop(compiler.method)
|
334
|
-
end
|
335
|
-
end
|
336
|
-
|
337
|
-
def call_special(compiler, target, target_type, parameters, expression)
|
338
|
-
target_type ||= compiler.inferred_type(target)
|
339
|
-
compiler.visit(target, true)
|
340
|
-
|
341
|
-
# if expression, void methods return the called object,
|
342
|
-
# for consistency and chaining
|
343
|
-
# TODO: inference phase needs to track that signature is
|
344
|
-
# void but actual type is callee
|
345
|
-
if expression && void?
|
346
|
-
compiler.method.dup
|
347
|
-
end
|
348
|
-
|
349
|
-
convert_args(compiler, parameters)
|
350
|
-
if target_type.interface?
|
351
|
-
raise "interfaces should not receive call_special"
|
352
|
-
else
|
353
|
-
compiler.method.invokespecial(
|
354
|
-
target_type,
|
355
|
-
name,
|
356
|
-
[@member.return_type, *@member.argument_types])
|
357
|
-
end
|
358
|
-
|
359
|
-
unless expression || void?
|
360
|
-
return_type.pop(compiler.method)
|
361
|
-
end
|
362
|
-
end
|
363
|
-
end
|
364
|
-
|
365
|
-
class JavaStaticMethod < JavaMethod
|
366
|
-
def call(compiler, ast, expression, parameters=nil)
|
367
|
-
target = declaring_class
|
368
|
-
parameters ||= ast.parameters
|
369
|
-
convert_args(compiler, parameters)
|
370
|
-
compiler.method.invokestatic(
|
371
|
-
target,
|
372
|
-
name,
|
373
|
-
[@member.return_type, *@member.argument_types])
|
374
|
-
# if expression, void static methods return null, for consistency
|
375
|
-
# TODO: inference phase needs to track that signature is void
|
376
|
-
# but actual type is null object
|
377
|
-
compiler.method.aconst_null if expression && void?
|
378
|
-
return_type.pop(compiler.method) unless expression || void?
|
379
|
-
end
|
380
|
-
|
381
|
-
def accept(visitor, expression)
|
382
|
-
visitor.visitStaticMethodCall(self, expression)
|
383
|
-
end
|
384
|
-
|
385
|
-
def kind
|
386
|
-
Java::OrgMirahJvmTypes::MemberKind::STATIC_METHOD
|
387
|
-
end
|
388
|
-
end
|
389
|
-
|
390
|
-
class JavaDynamicMethod < JavaMethod
|
391
|
-
def initialize(type_system, name, *argument_types)
|
392
|
-
super(type_system, nil)
|
393
|
-
@name = name
|
394
|
-
@argument_types = argument_types
|
395
|
-
end
|
396
|
-
|
397
|
-
def return_type
|
398
|
-
@types.type(nil, 'dynamic')
|
399
|
-
end
|
400
|
-
|
401
|
-
def declaring_class
|
402
|
-
java.lang.Object
|
403
|
-
end
|
404
|
-
|
405
|
-
def argument_types
|
406
|
-
@argument_types
|
407
|
-
end
|
408
|
-
|
409
|
-
def call(compiler, ast, expression, parameters=nil)
|
410
|
-
unless compiler.respond_to?(:supports_invokedynamic?) && compiler.supports_invokedynamic?
|
411
|
-
raise Mirah::MirahError, "Target JVM version: #{compiler.target_jvm_version} doesn't support invoke dynamic"
|
412
|
-
end
|
413
|
-
target = compiler.inferred_type(ast.target)
|
414
|
-
compiler.visit(ast.target, true)
|
415
|
-
|
416
|
-
parameters ||= ast.parameters
|
417
|
-
parameters.each do |param|
|
418
|
-
compiler.visit(param, true)
|
419
|
-
end
|
420
|
-
handle = compiler.method.h_invokestatic(
|
421
|
-
org.dynalang.dynalink.DefaultBootstrapper,
|
422
|
-
"bootstrap",
|
423
|
-
java.lang.invoke.CallSite,
|
424
|
-
java.lang.invoke.MethodHandles::Lookup,
|
425
|
-
java.lang.String,
|
426
|
-
java.lang.invoke.MethodType)
|
427
|
-
compiler.method.invokedynamic(
|
428
|
-
"dyn:callPropWithThis:#{name}",
|
429
|
-
[return_type, target, *@argument_types],
|
430
|
-
handle)
|
431
|
-
|
432
|
-
unless expression
|
433
|
-
return_type.pop(compiler.method)
|
434
|
-
end
|
435
|
-
end
|
436
|
-
end
|
437
|
-
|
438
|
-
class JavaFieldAccessor < JavaMethod
|
439
|
-
def field?
|
440
|
-
true
|
441
|
-
end
|
442
|
-
|
443
|
-
def return_type
|
444
|
-
@types.type(nil, @member.type)
|
445
|
-
end
|
446
|
-
|
447
|
-
def public?
|
448
|
-
@member.public?
|
449
|
-
end
|
450
|
-
|
451
|
-
def final?
|
452
|
-
@member.final?
|
453
|
-
end
|
454
|
-
end
|
455
|
-
|
456
|
-
class JavaFieldGetter < JavaFieldAccessor
|
457
|
-
def argument_types
|
458
|
-
[]
|
459
|
-
end
|
460
|
-
|
461
|
-
def call(compiler, ast, expression, parameters=nil)
|
462
|
-
target = compiler.inferred_type(ast.target)
|
463
|
-
|
464
|
-
# TODO: assert that no args are being passed, though that should have failed lookup
|
465
|
-
|
466
|
-
if expression
|
467
|
-
if @member.static?
|
468
|
-
compiler.method.getstatic(target, name, @member.type)
|
469
|
-
else
|
470
|
-
compiler.visit(ast.target, true)
|
471
|
-
compiler.method.getfield(target, name, @member.type)
|
472
|
-
end
|
473
|
-
end
|
474
|
-
end
|
475
|
-
|
476
|
-
def accept(visitor, expression)
|
477
|
-
if self.static?
|
478
|
-
visitor.visitStaticFieldAccess(self, expression)
|
479
|
-
else
|
480
|
-
visitor.visitFieldAccess(self, expression)
|
481
|
-
end
|
482
|
-
end
|
483
|
-
|
484
|
-
def kind
|
485
|
-
if self.static?
|
486
|
-
Java::OrgMirahJvmTypes::MemberKind::STATIC_FIELD_ACCESS
|
487
|
-
else
|
488
|
-
Java::OrgMirahJvmTypes::MemberKind::FIELD_ACCESS
|
489
|
-
end
|
490
|
-
end
|
491
|
-
end
|
492
|
-
|
493
|
-
class JavaFieldSetter < JavaFieldAccessor
|
494
|
-
def return_type
|
495
|
-
@types.type(nil, @member.type)
|
496
|
-
end
|
497
|
-
|
498
|
-
def argument_types
|
499
|
-
[@types.type(nil, @member.type)]
|
500
|
-
end
|
501
|
-
|
502
|
-
def call(compiler, ast, expression, parameters=nil)
|
503
|
-
target = compiler.inferred_type(ast.target)
|
504
|
-
|
505
|
-
# TODO: assert that no args are being passed, though that should have failed lookup
|
506
|
-
|
507
|
-
parameters ||= ast.parameters
|
508
|
-
if @member.static?
|
509
|
-
convert_args(compiler, parameters)
|
510
|
-
compiler.method.dup if expression
|
511
|
-
compiler.method.putstatic(target, name, @member.type)
|
512
|
-
else
|
513
|
-
compiler.visit(ast.target, true)
|
514
|
-
convert_args(compiler, parameters)
|
515
|
-
compiler.method.dup_x2 if expression
|
516
|
-
compiler.method.putfield(target, name, @member.type)
|
517
|
-
end
|
518
|
-
end
|
519
|
-
|
520
|
-
def accept(visitor, expression)
|
521
|
-
if self.static?
|
522
|
-
visitor.visitStaticFieldAssign(self, expression)
|
523
|
-
else
|
524
|
-
visitor.visitFieldAssign(self, expression)
|
525
|
-
end
|
526
|
-
end
|
527
|
-
|
528
|
-
def kind
|
529
|
-
if self.static?
|
530
|
-
Java::OrgMirahJvmTypes::MemberKind::STATIC_FIELD_ASSIGN
|
531
|
-
else
|
532
|
-
Java::OrgMirahJvmTypes::MemberKind::FIELD_ASSIGN
|
533
|
-
end
|
534
|
-
end
|
535
|
-
end
|
536
|
-
|
537
|
-
class MirahMember
|
538
|
-
attr_reader :name, :argument_types, :declaring_class, :return_type
|
539
|
-
attr_reader :exception_types
|
540
|
-
|
541
|
-
def initialize(klass, name, args, return_type, static, exceptions)
|
542
|
-
if return_type.name == 'void' || return_type.name == ':unreachable'
|
543
|
-
return_type = nil
|
544
|
-
end
|
545
|
-
@declaring_class = klass
|
546
|
-
@name = name
|
547
|
-
@argument_types = args
|
548
|
-
@return_type = return_type
|
549
|
-
@static = static
|
550
|
-
@exception_types = exceptions || []
|
551
|
-
end
|
552
|
-
|
553
|
-
def static?
|
554
|
-
@static
|
555
|
-
end
|
556
|
-
|
557
|
-
def abstract?
|
558
|
-
@declaring_class.interface?
|
559
|
-
end
|
560
|
-
|
561
|
-
def varargs?
|
562
|
-
false
|
563
|
-
end
|
564
|
-
|
565
|
-
def isVararg
|
566
|
-
varargs?
|
567
|
-
end
|
568
|
-
end
|
569
|
-
|
570
|
-
class Type
|
571
|
-
java_import "org.mirah.jvm.types.JVMMethod" rescue nil
|
572
|
-
|
573
|
-
def method_listeners
|
574
|
-
if meta?
|
575
|
-
unmeta.method_listeners
|
576
|
-
else
|
577
|
-
@method_listeners ||= {}
|
578
|
-
end
|
579
|
-
end
|
580
|
-
|
581
|
-
def method_updated(name)
|
582
|
-
listeners = method_listeners[name]
|
583
|
-
listeners.values.each do |l|
|
584
|
-
if l.kind_of?(Proc)
|
585
|
-
l.call(name)
|
586
|
-
else
|
587
|
-
l.method_updated(name)
|
588
|
-
end
|
589
|
-
end if listeners
|
590
|
-
end
|
591
|
-
|
592
|
-
def add_method_listener(name, listener=nil, &block)
|
593
|
-
listeners = method_listeners[name] ||= {}
|
594
|
-
if listener
|
595
|
-
unless listener.respond_to?(:method_updated) || listener.kind_of?(Proc)
|
596
|
-
raise "Invalid listener"
|
597
|
-
end
|
598
|
-
listeners[listener] = listener
|
599
|
-
else
|
600
|
-
listeners[block] = block
|
601
|
-
end
|
602
|
-
if !self.meta? && jvm_type && super_class_valid?
|
603
|
-
superclass.add_method_listener(name, self)
|
604
|
-
end
|
605
|
-
interfaces.each {|i| i.add_method_listener(name, self) unless i.isError}
|
606
|
-
end
|
607
|
-
|
608
|
-
# TODO take a scope and check visibility
|
609
|
-
def find_callable_macros(name)
|
610
|
-
macros = find_callable_macros2 name
|
611
|
-
macros.concat collect_up_interface_tree {|interface| interface.declared_macros(name) }
|
612
|
-
macros
|
613
|
-
end
|
614
|
-
|
615
|
-
def find_callable_macros2(name)
|
616
|
-
collect_up_inheritance_tree {|type| type.declared_macros name }
|
617
|
-
end
|
618
|
-
|
619
|
-
def find_callable_static_methods(name)
|
620
|
-
collect_up_inheritance_tree { |type| type.declared_class_methods(name) }
|
621
|
-
end
|
622
|
-
|
623
|
-
# TODO take a scope and check visibility
|
624
|
-
def find_callable_methods(name, include_interfaces=false, &proc)
|
625
|
-
if block_given?
|
626
|
-
add_method_listener(name) {proc.call(find_callable_methods(name))}
|
627
|
-
proc.call(find_callable_methods(name))
|
628
|
-
return
|
629
|
-
end
|
630
|
-
|
631
|
-
methods = find_callable_methods2 name
|
632
|
-
|
633
|
-
if self.interface? || include_interfaces # TODO || self.abstract?
|
634
|
-
methods.concat collect_up_interface_tree { |interface| interface.declared_instance_methods(name) }
|
635
|
-
end
|
636
|
-
methods
|
637
|
-
end
|
638
|
-
|
639
|
-
def find_callable_methods2(name)
|
640
|
-
collect_up_inheritance_tree { |type| type.declared_instance_methods(name) }
|
641
|
-
end
|
642
|
-
|
643
|
-
def get_method(name, args)
|
644
|
-
method = find_method(self, name, args, nil, meta?)
|
645
|
-
unless method
|
646
|
-
# Allow constant narrowing for assignment methods
|
647
|
-
if name =~ /=$/ && args[-1].respond_to?(:narrow!)
|
648
|
-
if args[-1].narrow!
|
649
|
-
method = find_method(self, name, args, meta?)
|
650
|
-
end
|
651
|
-
end
|
652
|
-
end
|
653
|
-
method
|
654
|
-
end
|
655
|
-
|
656
|
-
def constructor(*types)
|
657
|
-
begin
|
658
|
-
constructor = jvm_type.getConstructor(*bitescript_signatures(types))
|
659
|
-
return JavaConstructor.new(@type_system, constructor) if constructor
|
660
|
-
rescue => ex
|
661
|
-
log("#{ex.message}\n#{ex.backtrace.join("\n")}")
|
662
|
-
end
|
663
|
-
raise NameError, "No constructor #{name}(#{types.join ', '})"
|
664
|
-
end
|
665
|
-
|
666
|
-
def java_method(name, *types)
|
667
|
-
intrinsic = intrinsics[name][types]
|
668
|
-
return intrinsic if intrinsic
|
669
|
-
jvm_types = types.map {|type| type.jvm_type}
|
670
|
-
|
671
|
-
return JavaDynamicMethod.new(@type_system, name, *jvm_types) if dynamic?
|
672
|
-
|
673
|
-
begin
|
674
|
-
method = jvm_type.getDeclaredMethod(name, *bitescript_signatures(types)) if jvm_type
|
675
|
-
|
676
|
-
if method.nil? && superclass
|
677
|
-
method = superclass.java_method(name, *types) rescue nil
|
678
|
-
end
|
679
|
-
|
680
|
-
if method.nil? && jvm_type && jvm_type.abstract?
|
681
|
-
interfaces.each do |interface|
|
682
|
-
method = interface.java_method(name, *types) rescue nil
|
683
|
-
break if method
|
684
|
-
end
|
685
|
-
end
|
686
|
-
|
687
|
-
return method if method.kind_of?(JavaCallable)
|
688
|
-
if method && method.static? == meta?
|
689
|
-
return wrap_jvm_method method
|
690
|
-
end
|
691
|
-
rescue => ex
|
692
|
-
log("#{ex.message}\n#{ex.backtrace.join("\n")}")
|
693
|
-
end
|
694
|
-
raise NameError, "No method #{self.name}.#{name}(#{types.join ', '})"
|
695
|
-
end
|
696
|
-
|
697
|
-
def declared_instance_methods(name=nil)
|
698
|
-
all_declared_jvm_methods(name).reject{ |method| method.static? && !method.synthetic? } +
|
699
|
-
(meta? ? unmeta : self).declared_intrinsics(name)
|
700
|
-
end
|
701
|
-
|
702
|
-
def declared_class_methods(name=nil)
|
703
|
-
all_declared_jvm_methods(name).select{ |method| method.static? && !method.synthetic? } +
|
704
|
-
meta.declared_intrinsics(name)
|
705
|
-
end
|
706
|
-
|
707
|
-
def declared_constructors
|
708
|
-
jvm_type.getConstructors.map do |method|
|
709
|
-
JavaConstructor.new(@type_system, method)
|
710
|
-
end
|
711
|
-
end
|
712
|
-
|
713
|
-
def field_getter(name)
|
714
|
-
field = jvm_field(name)
|
715
|
-
return nil unless field
|
716
|
-
|
717
|
-
JavaFieldGetter.new(@type_system, field)
|
718
|
-
end
|
719
|
-
|
720
|
-
def field_setter(name)
|
721
|
-
field = jvm_field(name)
|
722
|
-
return nil unless field
|
723
|
-
|
724
|
-
JavaFieldSetter.new(@type_system, field)
|
725
|
-
end
|
726
|
-
|
727
|
-
def inner_class_getter(name)
|
728
|
-
full_name = "#{self.name}$#{name}"
|
729
|
-
inner_class = @type_system.type(nil, full_name) rescue nil
|
730
|
-
return unless inner_class
|
731
|
-
|
732
|
-
inner_class.inner_class = true
|
733
|
-
macro = Macro.new(self, name, []) do |call, typer|
|
734
|
-
Mirah::AST::Constant.new(call.position, Mirah::AST::SimpleString.new(call.position, full_name))
|
735
|
-
end
|
736
|
-
intrinsics[name][[]] = macro
|
737
|
-
end
|
738
|
-
|
739
|
-
def getDeclaredFields
|
740
|
-
@member.getDeclaredFields.to_java(JVMMethod)
|
741
|
-
end
|
742
|
-
|
743
|
-
def getDeclaredField(name)
|
744
|
-
@member.getDeclaredField(name)
|
745
|
-
end
|
746
|
-
|
747
|
-
def hasStaticField(name)
|
748
|
-
f = getDeclaredField(name)
|
749
|
-
f && f.static?
|
750
|
-
end
|
751
|
-
|
752
|
-
protected
|
753
|
-
|
754
|
-
def find_interfaces
|
755
|
-
collect_up_inheritance_tree {|type| type.interfaces }
|
756
|
-
end
|
757
|
-
|
758
|
-
def collect_up_interface_tree &block
|
759
|
-
interfaces = find_interfaces
|
760
|
-
things = []
|
761
|
-
seen = {}
|
762
|
-
until interfaces.empty?
|
763
|
-
interface = interfaces.pop
|
764
|
-
next if seen[interface]
|
765
|
-
seen[interface] = true
|
766
|
-
interfaces.concat(interface.interfaces)
|
767
|
-
new_things = block.call interface
|
768
|
-
things.concat new_things if new_things
|
769
|
-
end
|
770
|
-
things
|
771
|
-
end
|
772
|
-
|
773
|
-
def collect_up_inheritance_tree(&block)
|
774
|
-
things = []
|
775
|
-
new_things = block.call(self)
|
776
|
-
things.concat new_things if new_things
|
777
|
-
if super_class_valid?
|
778
|
-
things.concat superclass.collect_up_inheritance_tree(&block)
|
779
|
-
end
|
780
|
-
things
|
781
|
-
end
|
782
|
-
|
783
|
-
private
|
784
|
-
|
785
|
-
def super_class_valid?
|
786
|
-
superclass && !superclass.error?
|
787
|
-
end
|
788
|
-
|
789
|
-
def all_declared_jvm_methods(name=nil)
|
790
|
-
return [] if !jvm_type || (meta? ? unmeta : self).array?
|
791
|
-
|
792
|
-
jvm_type.getDeclaredMethods(name).map { |method| wrap_jvm_method method }
|
793
|
-
end
|
794
|
-
|
795
|
-
def wrap_jvm_method method
|
796
|
-
if (method.static? && !method.synthetic?)
|
797
|
-
JavaStaticMethod.new(@type_system, method)
|
798
|
-
else
|
799
|
-
JavaMethod.new(@type_system, method)
|
800
|
-
end
|
801
|
-
end
|
802
|
-
|
803
|
-
def jvm_field(name)
|
804
|
-
return nil unless jvm_type
|
805
|
-
jvm_type.getField(name)
|
806
|
-
end
|
807
|
-
|
808
|
-
def bitescript_signatures types
|
809
|
-
types.map {|type| BiteScript::Signature.class_id(type)}
|
810
|
-
end
|
811
|
-
end
|
812
|
-
|
813
|
-
class TypeDefinition
|
814
|
-
java_import "org.mirah.jvm.types.JVMMethod" rescue nil
|
815
|
-
|
816
|
-
def java_method(name, *types)
|
817
|
-
method = first_matching instance_methods[name], types
|
818
|
-
return method if method
|
819
|
-
intrinsic = intrinsics[name][types]
|
820
|
-
return intrinsic if intrinsic
|
821
|
-
raise NameError, "No method #{self.name}.#{name}(#{types.join ', '})"
|
822
|
-
end
|
823
|
-
|
824
|
-
def java_static_method(name, *types)
|
825
|
-
method = first_matching static_methods[name], types
|
826
|
-
return method if method
|
827
|
-
intrinsic = meta.intrinsics[name][types]
|
828
|
-
return intrinsic if intrinsic
|
829
|
-
raise NameError, "No method #{self.name}.#{name}(#{types.join ', '})"
|
830
|
-
end
|
831
|
-
|
832
|
-
def constructor(*types)
|
833
|
-
constructor = first_matching constructors, types
|
834
|
-
return constructor if constructor
|
835
|
-
raise NameError, "No constructor #{name}(#{types.join ', '})"
|
836
|
-
end
|
837
|
-
|
838
|
-
def declared_instance_methods(name=nil)
|
839
|
-
declared_methods self, instance_methods, name
|
840
|
-
end
|
841
|
-
|
842
|
-
def declared_class_methods(name=nil)
|
843
|
-
declared_methods meta, static_methods, name
|
844
|
-
end
|
845
|
-
|
846
|
-
def constructors
|
847
|
-
if @constructors.nil?
|
848
|
-
@constructors = []
|
849
|
-
declare_method('initialize', [], self, [])
|
850
|
-
@have_default_constructor = true
|
851
|
-
end
|
852
|
-
@constructors
|
853
|
-
end
|
854
|
-
alias :declared_constructors :constructors
|
855
|
-
|
856
|
-
def instance_methods
|
857
|
-
@instance_methods ||= Hash.new {|h, k| h[k] = []}
|
858
|
-
end
|
859
|
-
|
860
|
-
def static_methods
|
861
|
-
@static_methods ||= Hash.new {|h, k| h[k] = []}
|
862
|
-
end
|
863
|
-
|
864
|
-
def getDeclaredFields
|
865
|
-
@fields.values.to_java(JVMMethod)
|
866
|
-
end
|
867
|
-
|
868
|
-
def getDeclaredField(name)
|
869
|
-
@fields[name]
|
870
|
-
end
|
871
|
-
|
872
|
-
def hasStaticField(name)
|
873
|
-
f = getDeclaredField(name)
|
874
|
-
f && f.static?
|
875
|
-
end
|
876
|
-
|
877
|
-
def declared_fields
|
878
|
-
@fields ||= {}
|
879
|
-
end
|
880
|
-
|
881
|
-
def declare_field(name, type, static)
|
882
|
-
declared_fields[name] ||= MirahMember.new(self, name, [], type, static, [])
|
883
|
-
end
|
884
|
-
|
885
|
-
def declare_method(name, arguments, type, exceptions)
|
886
|
-
raise "Bad args" unless arguments.all?
|
887
|
-
if type.isError
|
888
|
-
instance_methods.delete(name)
|
889
|
-
method_updated(name)
|
890
|
-
return
|
891
|
-
end
|
892
|
-
member = MirahMember.new(self, name, arguments, type, false, exceptions)
|
893
|
-
if name == 'initialize'
|
894
|
-
# The ordering is important here:
|
895
|
-
# The first call to constructors initializes @have_default_constructor.
|
896
|
-
if constructors.size == 1 && @have_default_constructor
|
897
|
-
constructors.clear
|
898
|
-
@have_default_constructor = false
|
899
|
-
elsif constructors.size > 1 && @have_default_constructor
|
900
|
-
raise "Invalid state: default constructor but #{constructors.size} constructors"
|
901
|
-
end
|
902
|
-
constructors << JavaConstructor.new(@type_system, member)
|
903
|
-
else
|
904
|
-
instance_methods[name] << JavaMethod.new(@type_system, member)
|
905
|
-
end
|
906
|
-
method_updated(name)
|
907
|
-
end
|
908
|
-
|
909
|
-
def declare_static_method(name, arguments, type, exceptions)
|
910
|
-
if type.isError
|
911
|
-
static_methods.delete(name)
|
912
|
-
else
|
913
|
-
member = MirahMember.new(self, name, arguments, type, true, exceptions)
|
914
|
-
static_methods[name] << JavaStaticMethod.new(@type_system, member)
|
915
|
-
end
|
916
|
-
method_updated(name)
|
917
|
-
end
|
918
|
-
|
919
|
-
def interface?
|
920
|
-
false
|
921
|
-
end
|
922
|
-
|
923
|
-
def field_getter(name)
|
924
|
-
nil
|
925
|
-
end
|
926
|
-
|
927
|
-
def field_setter(name)
|
928
|
-
nil
|
929
|
-
end
|
930
|
-
|
931
|
-
private
|
932
|
-
|
933
|
-
def declared_methods target, method_hash, name
|
934
|
-
# should the declared intrinsics be first here? nh
|
935
|
-
target.declared_intrinsics(name) +
|
936
|
-
if name.nil?
|
937
|
-
method_hash.values.flatten
|
938
|
-
else
|
939
|
-
method_hash[name]
|
940
|
-
end
|
941
|
-
end
|
942
|
-
|
943
|
-
def first_matching method_list, types
|
944
|
-
method_list.find {|m| m.argument_types == types}
|
945
|
-
end
|
946
|
-
end
|
947
|
-
|
948
|
-
class TypeDefMeta
|
949
|
-
def constructor(*args)
|
950
|
-
unmeta.constructor(*args)
|
951
|
-
end
|
952
|
-
|
953
|
-
def java_method(*args)
|
954
|
-
unmeta.java_static_method(*args)
|
955
|
-
end
|
956
|
-
|
957
|
-
def declared_class_methods(name=nil)
|
958
|
-
unmeta.declared_class_methods(name)
|
959
|
-
end
|
960
|
-
|
961
|
-
def declared_instance_methods(name=nil)
|
962
|
-
unmeta.declared_instance_methods(name)
|
963
|
-
end
|
964
|
-
|
965
|
-
def field_getter(name)
|
966
|
-
nil
|
967
|
-
end
|
968
|
-
|
969
|
-
def field_setter(name)
|
970
|
-
nil
|
971
|
-
end
|
972
|
-
end
|
973
|
-
end
|