mirah 0.1.2-java → 0.1.3-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 +4 -4
- data/History.txt +225 -0
- data/Rakefile +108 -315
- data/TODO.md +100 -0
- data/bin/bundler +16 -0
- data/bin/rake +16 -0
- data/dist/mirahc.jar +0 -0
- data/examples/appengine/Readme +0 -1
- data/examples/literals.mirah +17 -0
- data/examples/macros/string_each_char.mirah +1 -1
- data/lib/mirah.rb +11 -21
- data/lib/mirah/transform/transformer.rb +1 -2
- data/lib/mirah/util/class_loader.rb +1 -1
- data/lib/mirah/util/logging.rb +0 -63
- data/lib/mirah/util/process_errors.rb +1 -0
- data/lib/mirah/version.rb +1 -1
- data/{examples/simple_class.mirah~ → test/artifacts/jar_test.rb} +7 -11
- data/{lib/mirah/commands.rb → test/artifacts/jruby_test.rb} +8 -5
- data/test/core/typer_test.rb +29 -11
- data/test/core/util/argument_processor_test.rb +24 -23
- data/test/core/util/class_loader_test.rb +7 -4
- data/test/core/util/{compilation_state_test.rb → jvm_version_test.rb} +20 -16
- data/test/fixtures/org/foo/ImplicitClassRetAnno.java +4 -0
- data/test/fixtures/org/foo/IntAnno.java +9 -0
- data/test/jvm/annotations_test.rb +11 -11
- data/test/jvm/blocks_test.rb +16 -12
- data/test/jvm/constructors_test.rb +8 -8
- data/test/jvm/enumerable_test.rb +48 -24
- data/test/jvm/generics_test.rb +3 -7
- data/test/jvm/import_test.rb +14 -0
- data/test/jvm/interface_test.rb +9 -24
- data/test/jvm/jvm_commands_test.rb +22 -4
- data/test/jvm/jvm_compiler_test.rb +124 -79
- data/test/jvm/list_extensions_test.rb +1 -1
- data/test/jvm/macros_test.rb +67 -14
- data/test/jvm/main_method_test.rb +1 -1
- data/test/jvm/new_backend_test_helper.rb +100 -3
- data/{lib/mirah/jvm/types/bitescript_ext.rb → test/jvm/static_fields_test.rb} +22 -21
- data/test/mirrors/base_type_test.rb +4 -3
- data/test/mirrors/bytecode_mirror_test.rb +35 -15
- data/test/mirrors/generics_test.rb +14 -5
- data/test/mirrors/member_test.rb +2 -1
- data/test/mirrors/method_lookup_test.rb +18 -6
- data/test/mirrors/mirrors_test.rb +87 -20
- data/test/mirrors/simple_async_mirror_loader_test.rb +7 -3
- data/test/mirrors/simple_mirror_loader_test.rb +5 -5
- data/test/test_helper.rb +25 -1
- metadata +18 -78
- data/bin/mirahp +0 -27
- data/bin/mirahp.cmd +0 -16
- data/examples/Fib.class +0 -0
- 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-newast-transitional.jar +0 -0
- data/javalib/mirah-parser.jar +0 -0
- data/javalib/mirah-util.jar +0 -0
- data/lib/mirah/ast.rb +0 -43
- data/lib/mirah/ast/scope.rb +0 -262
- data/lib/mirah/commands/base.rb +0 -59
- data/lib/mirah/commands/compile.rb +0 -39
- data/lib/mirah/commands/parse.rb +0 -36
- data/lib/mirah/commands/run.rb +0 -78
- data/lib/mirah/generator.rb +0 -150
- data/lib/mirah/jvm/compiler.rb +0 -50
- data/lib/mirah/jvm/compiler/base.rb +0 -421
- data/lib/mirah/jvm/compiler/jvm_bytecode.rb +0 -1194
- data/lib/mirah/jvm/method_lookup.rb +0 -307
- data/lib/mirah/jvm/types.rb +0 -45
- data/lib/mirah/jvm/types/array_type.rb +0 -60
- data/lib/mirah/jvm/types/ast_ext.rb +0 -31
- data/lib/mirah/jvm/types/basic_types.rb +0 -41
- data/lib/mirah/jvm/types/block_type.rb +0 -15
- data/lib/mirah/jvm/types/boolean.rb +0 -70
- data/lib/mirah/jvm/types/enumerable.rb +0 -80
- data/lib/mirah/jvm/types/extensions.rb +0 -110
- data/lib/mirah/jvm/types/factory.rb +0 -830
- data/lib/mirah/jvm/types/floats.rb +0 -99
- data/lib/mirah/jvm/types/generic_type.rb +0 -72
- data/lib/mirah/jvm/types/implicit_nil_type.rb +0 -29
- data/lib/mirah/jvm/types/integers.rb +0 -131
- data/lib/mirah/jvm/types/interface_definition.rb +0 -20
- data/lib/mirah/jvm/types/intrinsics.rb +0 -385
- data/lib/mirah/jvm/types/literals.rb +0 -89
- data/lib/mirah/jvm/types/meta_type.rb +0 -54
- data/lib/mirah/jvm/types/methods.rb +0 -946
- data/lib/mirah/jvm/types/null_type.rb +0 -39
- data/lib/mirah/jvm/types/number.rb +0 -184
- data/lib/mirah/jvm/types/primitive_type.rb +0 -76
- data/lib/mirah/jvm/types/source_mirror.rb +0 -274
- data/lib/mirah/jvm/types/type.rb +0 -311
- data/lib/mirah/jvm/types/type_definition.rb +0 -72
- data/lib/mirah/jvm/types/void_type.rb +0 -19
- data/lib/mirah/util/compilation_state.rb +0 -60
- data/test/core/commands_test.rb +0 -89
- data/test/core/generator_test.rb +0 -26
- data/test/fixtures/org/foo/LowerCaseInnerClass$inner.class +0 -0
- data/test/fixtures/org/foo/LowerCaseInnerClass.class +0 -0
- data/test/jvm/bytecode_test_helper.rb +0 -193
- data/test/jvm/factory_test.rb +0 -28
- data/test/jvm/java_typer_test.rb +0 -283
|
@@ -1,70 +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
|
-
module Mirah::JVM::Types
|
|
17
|
-
class BooleanType < PrimitiveType
|
|
18
|
-
def init_value(builder)
|
|
19
|
-
builder.iconst_0
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def prefix
|
|
23
|
-
'i'
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def add_intrinsics
|
|
27
|
-
args = [math_type]
|
|
28
|
-
add_method('==', args, ComparisonIntrinsic.new(self, '==', :eq, args))
|
|
29
|
-
add_method('!=', args, ComparisonIntrinsic.new(self, '!=', :ne, args))
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def math_type
|
|
33
|
-
@type_system.type(nil, 'boolean')
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def compile_widen(builder, type)
|
|
37
|
-
case type.name
|
|
38
|
-
when 'boolean'
|
|
39
|
-
when wrapper_name, 'java.lang.Object'
|
|
40
|
-
builder.invokestatic @wrapper, "valueOf", [@wrapper, builder.send(name)]
|
|
41
|
-
else
|
|
42
|
-
raise ArgumentError, "Invalid widening conversion from #{name} to #{type}"
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
# same as NumberType's
|
|
47
|
-
def compile_boolean_operator(compiler, op, negated, call, label)
|
|
48
|
-
# Promote the target or the argument if necessary
|
|
49
|
-
convert_args(compiler,
|
|
50
|
-
[call.target, *call.parameters],
|
|
51
|
-
[math_type, math_type])
|
|
52
|
-
if negated
|
|
53
|
-
op = invert_op(op)
|
|
54
|
-
end
|
|
55
|
-
if label
|
|
56
|
-
jump_if(compiler.method, op, label)
|
|
57
|
-
else
|
|
58
|
-
compiler.method.op_to_bool do |label|
|
|
59
|
-
jump_if(compiler.method, op, label)
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
# Same as IntegerType's
|
|
65
|
-
# bools are ints for comparison purposes
|
|
66
|
-
def jump_if(builder, op, label)
|
|
67
|
-
builder.send "if_icmp#{op}", label
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
end
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2010 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
|
-
module Mirah::JVM::Types
|
|
17
|
-
class Type
|
|
18
|
-
def expand_each(transformer, call)
|
|
19
|
-
arg_types = [Mirah::AST.block_type]
|
|
20
|
-
code = intrinsics['each'][arg_types].return_type
|
|
21
|
-
code.inline(transformer, call)
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def add_enumerable_macros
|
|
25
|
-
all_proc = proc do |transformer, call|
|
|
26
|
-
if !call.block
|
|
27
|
-
# We need to create a block that just returns the item passed to it
|
|
28
|
-
# First get a new temp for the block argument
|
|
29
|
-
var = transformer.tmp
|
|
30
|
-
# Parse a fake function call to create a block. Then pull of the
|
|
31
|
-
# block and attach it to the real call.
|
|
32
|
-
call.block = transformer.eval("foo {|#{var}| #{var}}").block
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
# Now that we've got a block we can transform it into a Loop.
|
|
36
|
-
forloop = expand_each(transformer, call)
|
|
37
|
-
|
|
38
|
-
# Start adding stuff to the loop.
|
|
39
|
-
# At the beginning of the loop we create a temp initialized to true
|
|
40
|
-
all = transformer.tmp
|
|
41
|
-
forloop.init << transformer.eval("#{all} = true")
|
|
42
|
-
|
|
43
|
-
# Now we want to wrap the body of the loop. Start off by using
|
|
44
|
-
# foo as a placeholder.
|
|
45
|
-
body = transformer.eval(
|
|
46
|
-
"unless foo;#{all} = false;break;end", '', forloop)
|
|
47
|
-
# Then replace foo with the real body.
|
|
48
|
-
body.condition.predicate = call.block.body
|
|
49
|
-
# And finally patch the new body back into the forloop.
|
|
50
|
-
forloop.body = call.block.body.parent = body
|
|
51
|
-
|
|
52
|
-
# Loops don't have a return value, so we need somewhere to
|
|
53
|
-
# put the result.
|
|
54
|
-
result = Mirah::AST::Body.new(call.parent, call.position)
|
|
55
|
-
result << forloop << transformer.eval("#{all}", '', nil, all)
|
|
56
|
-
end
|
|
57
|
-
add_macro('all?', &all_proc)
|
|
58
|
-
add_macro('all?', Mirah::AST.block_type, &all_proc)
|
|
59
|
-
|
|
60
|
-
any_proc = proc do |transformer, call|
|
|
61
|
-
if !call.block
|
|
62
|
-
var = transformer.tmp
|
|
63
|
-
call.block = transformer.eval("foo {|#{var}| #{var}}").block
|
|
64
|
-
end
|
|
65
|
-
forloop = expand_each(transformer, call)
|
|
66
|
-
any = transformer.tmp
|
|
67
|
-
forloop.init << transformer.eval("#{any} = false")
|
|
68
|
-
body = transformer.eval(
|
|
69
|
-
"if foo;#{any} = true;break;end", '', forloop)
|
|
70
|
-
body.condition.predicate = call.block.body
|
|
71
|
-
forloop.body = call.block.body.parent = body
|
|
72
|
-
|
|
73
|
-
result = Mirah::AST::Body.new(call.parent, call.position)
|
|
74
|
-
result << forloop << transformer.eval("#{any}", '', nil, any)
|
|
75
|
-
end
|
|
76
|
-
add_macro('any?', &any_proc)
|
|
77
|
-
add_macro('any?', Mirah::AST.block_type, &any_proc)
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
|
-
end
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2010 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/util/delegate'
|
|
17
|
-
|
|
18
|
-
module Mirah::JVM::Types
|
|
19
|
-
class ExtendedType < Mirah::Util::DelegateClass(Type)
|
|
20
|
-
def initialize(*args)
|
|
21
|
-
super
|
|
22
|
-
@static_includes = []
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def include(type)
|
|
26
|
-
@static_includes << type
|
|
27
|
-
self
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def meta
|
|
31
|
-
if meta?
|
|
32
|
-
self
|
|
33
|
-
else
|
|
34
|
-
__getobj__.meta
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def unmeta
|
|
39
|
-
if meta?
|
|
40
|
-
__getobj__.unmeta
|
|
41
|
-
else
|
|
42
|
-
self
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def get_method(name, args)
|
|
47
|
-
method = __getobj__.get_method(name, args)
|
|
48
|
-
return method if method
|
|
49
|
-
@static_includes.each do |type|
|
|
50
|
-
method = type.meta.get_method(name, args)
|
|
51
|
-
return method if method
|
|
52
|
-
end
|
|
53
|
-
nil
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def java_method(name, *types)
|
|
57
|
-
__getobj__.java_method(name, *types) || __included_method(name, types)
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def java_static_method(name, *types)
|
|
61
|
-
__getobj__.java_static_method(name, *types) || __included_method(name, types)
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
def declared_instance_methods(name=nil)
|
|
65
|
-
__combine_methods(__getobj__.declared_instance_methods, name)
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def declared_class_methods(name=nil)
|
|
69
|
-
__combine_methods(__getobj__.declared_class_methods, name)
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def find_callable_methods(name, include_interfaces=false)
|
|
73
|
-
__combine_methods(__getobj__.find_callable_methods(name, include_interfaces), name)
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def find_callable_static_methods(name)
|
|
77
|
-
__combine_methods(__getobj__.find_callable_static_methods(name), name)
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
def __combine_methods(basic_methods, name)
|
|
81
|
-
methods = {}
|
|
82
|
-
basic_methods.each do |method|
|
|
83
|
-
key = [method.name, method.argument_types, method.return_type]
|
|
84
|
-
methods[key] = method
|
|
85
|
-
end
|
|
86
|
-
@static_includes.each do |type|
|
|
87
|
-
type.declared_class_methods.each do |method|
|
|
88
|
-
next if name && method.name != name
|
|
89
|
-
key = [method.name, method.argument_types, method.return_type]
|
|
90
|
-
methods[key] ||= method
|
|
91
|
-
end
|
|
92
|
-
end
|
|
93
|
-
methods.values
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
def __included_method(name, types)
|
|
97
|
-
@static_includes.each do |type|
|
|
98
|
-
method = type.meta.java_method(name, *types)
|
|
99
|
-
return method if method
|
|
100
|
-
end
|
|
101
|
-
nil
|
|
102
|
-
end
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
class Type
|
|
106
|
-
def include(type)
|
|
107
|
-
ExtendedType.new(self).include(type)
|
|
108
|
-
end
|
|
109
|
-
end
|
|
110
|
-
end
|
|
@@ -1,830 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2010 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 'jruby'
|
|
17
|
-
require 'mirah/jvm/types/source_mirror'
|
|
18
|
-
module Mirah::JVM::Types
|
|
19
|
-
java_import 'org.mirah.typer.simple.SimpleTypes'
|
|
20
|
-
class TypeFactory < SimpleTypes
|
|
21
|
-
java_import 'org.mirah.typer.AssignableTypeFuture'
|
|
22
|
-
java_import 'org.mirah.typer.PickFirst'
|
|
23
|
-
java_import 'org.mirah.typer.BaseTypeFuture'
|
|
24
|
-
#java_import 'org.mirah.typer.BlockType'
|
|
25
|
-
java_import 'org.mirah.typer.ErrorType'
|
|
26
|
-
java_import 'org.mirah.typer.GenericTypeFuture'
|
|
27
|
-
java_import 'org.mirah.typer.MethodFuture'
|
|
28
|
-
java_import 'org.mirah.typer.MethodType'
|
|
29
|
-
java_import 'org.mirah.typer.SimpleFuture'
|
|
30
|
-
java_import 'org.mirah.typer.TypeFuture'
|
|
31
|
-
java_import 'org.mirah.typer.TypeSystem'
|
|
32
|
-
java_import 'org.mirah.typer.NarrowingTypeFuture'
|
|
33
|
-
java_import 'mirah.lang.ast.ClassDefinition'
|
|
34
|
-
java_import 'mirah.lang.ast.InterfaceDeclaration'
|
|
35
|
-
java_import 'mirah.lang.ast.Script'
|
|
36
|
-
java_import 'mirah.lang.ast.SimpleString'
|
|
37
|
-
include TypeSystem
|
|
38
|
-
include Mirah::Logging::Logged
|
|
39
|
-
|
|
40
|
-
begin
|
|
41
|
-
java_import 'org.mirah.builtins.Builtins'
|
|
42
|
-
rescue NameError
|
|
43
|
-
# We might be trying to compile mirah-builtins.jar, so just continue.
|
|
44
|
-
Builtins = nil
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
java_import 'java.net.URLClassLoader'
|
|
48
|
-
attr_accessor :package
|
|
49
|
-
attr_reader :known_types
|
|
50
|
-
|
|
51
|
-
class ParanoidHash < Hash
|
|
52
|
-
def []=(k, v)
|
|
53
|
-
raise ArgumentError, "Can't store nil for key #{k.inspect}" if v.nil?
|
|
54
|
-
super(k, v)
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def initialize
|
|
59
|
-
super(":unused")
|
|
60
|
-
@known_types = ParanoidHash.new
|
|
61
|
-
@anonymous_classes = Hash.new {|h, k| h[k] = 0}
|
|
62
|
-
@declarations = []
|
|
63
|
-
@mirrors = {}
|
|
64
|
-
@futures = {}
|
|
65
|
-
@fields = {}
|
|
66
|
-
create_basic_types
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def initialize_copy(other)
|
|
70
|
-
@known_types = other.known_types.dup
|
|
71
|
-
@known_types.delete_if do |key, value|
|
|
72
|
-
value.basic_type.kind_of?(Mirah::JVM::Types::TypeDefinition)
|
|
73
|
-
end
|
|
74
|
-
@declarations = []
|
|
75
|
-
@futures = {}
|
|
76
|
-
@fields = {}
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
def maybe_initialize_builtins(compiler)
|
|
80
|
-
if Builtins
|
|
81
|
-
begin
|
|
82
|
-
Builtins.initialize_builtins(compiler.type_system)
|
|
83
|
-
rescue NativeException => ex
|
|
84
|
-
error("Error initializing builtins", ex.cause)
|
|
85
|
-
rescue => ex
|
|
86
|
-
error("Error initializing builtins: #{ex.message}\n\t#{ex.backtrace.join("\n\t")}")
|
|
87
|
-
end
|
|
88
|
-
else
|
|
89
|
-
warning "Unable to initialize builtins"
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
def wrap(resolved_type)
|
|
94
|
-
future = BaseTypeFuture.new(nil)
|
|
95
|
-
future.resolved(resolved_type) if resolved_type
|
|
96
|
-
future
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
def cache_and_wrap(resolved_type)
|
|
100
|
-
@futures[resolved_type.name] ||= wrap(resolved_type)
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
def cache_and_wrap_type(name)
|
|
104
|
-
@futures[name] ||= begin
|
|
105
|
-
type = type(nil, name)
|
|
106
|
-
wrapper = wrap(type)
|
|
107
|
-
wrapper.resolved(ErrorType.new([["Cannot find class #{name}"]])) if type.nil?
|
|
108
|
-
wrapper
|
|
109
|
-
end
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
# TypeSystem methods
|
|
113
|
-
def addDefaultImports(scope)
|
|
114
|
-
scope.import('java.lang.*', '*')
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
def getNullType; cache_and_wrap_type('null') end
|
|
118
|
-
def getImplicitNilType; cache_and_wrap_type('implicit_nil') end
|
|
119
|
-
def getVoidType; cache_and_wrap_type('void') end
|
|
120
|
-
def getBaseExceptionType; cache_and_wrap_type('java.lang.Throwable') end
|
|
121
|
-
def getDefaultExceptionType; cache_and_wrap_type('java.lang.Exception') end
|
|
122
|
-
def getHashType; cache_and_wrap_type('java.util.HashMap') end
|
|
123
|
-
def getRegexType; cache_and_wrap_type('java.util.regex.Pattern') end
|
|
124
|
-
def getStringType; cache_and_wrap_type('java.lang.String') end
|
|
125
|
-
def getBooleanType; cache_and_wrap_type('boolean') end
|
|
126
|
-
|
|
127
|
-
def getFixnumType(value)
|
|
128
|
-
long = java.lang.Long.new(value)
|
|
129
|
-
if long.int_value != value
|
|
130
|
-
cache_and_wrap_type('long')
|
|
131
|
-
elsif long.short_value != value
|
|
132
|
-
cache_and_wrap_type('int')
|
|
133
|
-
elsif long.byte_value != value
|
|
134
|
-
wide = type(nil, 'int')
|
|
135
|
-
narrow = type(nil, 'short')
|
|
136
|
-
NarrowingTypeFuture.new(nil, wide, narrow)
|
|
137
|
-
else
|
|
138
|
-
wide = type(nil, 'int')
|
|
139
|
-
narrow = type(nil, 'byte')
|
|
140
|
-
NarrowingTypeFuture.new(nil, wide, narrow)
|
|
141
|
-
end
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
def getCharType(value) cache_and_wrap_type('char') end
|
|
145
|
-
|
|
146
|
-
def getFloatType(value)
|
|
147
|
-
d = java.lang.Double.new(value)
|
|
148
|
-
if d.float_value != value
|
|
149
|
-
cache_and_wrap_type('double')
|
|
150
|
-
else
|
|
151
|
-
wide = type(nil, 'double')
|
|
152
|
-
narrow = type(nil, 'float')
|
|
153
|
-
NarrowingTypeFuture.new(nil, wide, narrow)
|
|
154
|
-
end
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
def getMetaType(type)
|
|
158
|
-
if type.kind_of?(Type)
|
|
159
|
-
type.meta
|
|
160
|
-
else
|
|
161
|
-
future = BaseTypeFuture.new(nil)
|
|
162
|
-
type.on_update {|_, resolved| future.resolved(resolved.meta)}
|
|
163
|
-
future.position_set(type.position)
|
|
164
|
-
future.error_message_set(type.error_message)
|
|
165
|
-
future
|
|
166
|
-
end
|
|
167
|
-
end
|
|
168
|
-
|
|
169
|
-
def getSuperClass(future)
|
|
170
|
-
superclass = BaseTypeFuture.new(nil)
|
|
171
|
-
future.on_update do |_, type|
|
|
172
|
-
superclass.resolved(type.superclass)
|
|
173
|
-
end
|
|
174
|
-
superclass
|
|
175
|
-
end
|
|
176
|
-
|
|
177
|
-
def getArrayType(type)
|
|
178
|
-
if type.kind_of?(Type)
|
|
179
|
-
type.array_type
|
|
180
|
-
else
|
|
181
|
-
future = BaseTypeFuture.new(nil)
|
|
182
|
-
type.on_update {|_, resolved| future.resolved(resolved.array_type)}
|
|
183
|
-
future
|
|
184
|
-
end
|
|
185
|
-
end
|
|
186
|
-
|
|
187
|
-
def box(type)
|
|
188
|
-
boxed = BaseTypeFuture.new(nil)
|
|
189
|
-
type.on_update do |_, resolved|
|
|
190
|
-
if resolved.isError || !resolved.primitive?
|
|
191
|
-
boxed.resolved(resolved)
|
|
192
|
-
else
|
|
193
|
-
boxed.resolved(resolved.box_type)
|
|
194
|
-
end
|
|
195
|
-
end
|
|
196
|
-
boxed
|
|
197
|
-
end
|
|
198
|
-
|
|
199
|
-
def getArrayLiteralType(type, position)
|
|
200
|
-
result = Mirah::JVM::Types::GenericType.new(type(nil, 'java.util.List')) # Upgrade to a generic type.
|
|
201
|
-
variable = result.type_parameters[0]
|
|
202
|
-
result.type_parameter_map[variable.name] = _build_generic_type_future(variable.bounds, position)
|
|
203
|
-
result.type_parameter_map[variable.name].assign(box(type), position)
|
|
204
|
-
wrap(result)
|
|
205
|
-
rescue => ex
|
|
206
|
-
Mirah.print_error("Error inferring generics: #{ex.message}", position)
|
|
207
|
-
log("Error inferring generics: #{ex.message}\n#{ex.backtrace.join("\n")}")
|
|
208
|
-
cache_and_wrap_type('java.util.List')
|
|
209
|
-
end
|
|
210
|
-
|
|
211
|
-
def getHashLiteralType(key_type, value_type, position)
|
|
212
|
-
result = Mirah::JVM::Types::GenericType.new(type(nil, 'java.util.HashMap')) # Upgrade to a generic type.
|
|
213
|
-
generic_key, generic_value = result.type_parameters
|
|
214
|
-
for variable, type in [[generic_key, key_type], [generic_value, value_type]]
|
|
215
|
-
result.type_parameter_map[variable.name] = _build_generic_type_future(variable.bounds, position)
|
|
216
|
-
result.type_parameter_map[variable.name].assign(box(type), position)
|
|
217
|
-
end
|
|
218
|
-
wrap(result)
|
|
219
|
-
rescue => ex
|
|
220
|
-
Mirah.print_error("Error inferring generics: #{ex.message}", position)
|
|
221
|
-
log("Error inferring generics: #{ex.message}\n#{ex.backtrace.join("\n")}")
|
|
222
|
-
cache_and_wrap_type('java.util.HashMap')
|
|
223
|
-
end
|
|
224
|
-
|
|
225
|
-
def get(scope, typeref)
|
|
226
|
-
basic_type = if scope.nil?
|
|
227
|
-
cache_and_wrap_type(typeref.name)
|
|
228
|
-
else
|
|
229
|
-
imports = scope.imports
|
|
230
|
-
name = typeref.name
|
|
231
|
-
name = imports[name] while imports.include?(name)
|
|
232
|
-
types = [ cache_and_wrap_type(name), nil ]
|
|
233
|
-
packages = []
|
|
234
|
-
packages << scope.package if scope.package && scope.package != ''
|
|
235
|
-
(packages + scope.search_packages).each do |package|
|
|
236
|
-
types << cache_and_wrap_type("#{package}.#{name}")
|
|
237
|
-
types << nil
|
|
238
|
-
end
|
|
239
|
-
|
|
240
|
-
future = PickFirst.new(types, nil)
|
|
241
|
-
future.position_set(typeref.position)
|
|
242
|
-
future.error_message_set("Cannot find class #{typeref.name}")
|
|
243
|
-
future
|
|
244
|
-
end
|
|
245
|
-
if typeref.isArray
|
|
246
|
-
getArrayType(basic_type)
|
|
247
|
-
elsif typeref.isStatic
|
|
248
|
-
getMetaType(basic_type)
|
|
249
|
-
else
|
|
250
|
-
basic_type
|
|
251
|
-
end
|
|
252
|
-
end
|
|
253
|
-
|
|
254
|
-
def getLocalType(scope, name, position)
|
|
255
|
-
scope.local_type(name, position)
|
|
256
|
-
end
|
|
257
|
-
|
|
258
|
-
def getMethodType(call)
|
|
259
|
-
target = call.resolved_target
|
|
260
|
-
argTypes = call.resolved_parameters
|
|
261
|
-
macro_types = call.parameter_nodes.map do |node|
|
|
262
|
-
get_type(node.java_class.name)
|
|
263
|
-
end if call.parameter_nodes
|
|
264
|
-
_find_method_type(call.scope, target, call.name, argTypes, macro_types, call.position)
|
|
265
|
-
rescue => ex
|
|
266
|
-
Mirah.print_error("Error getting method type #{target.name}.#{call.name}: #{ex.message}", call.position)
|
|
267
|
-
puts ex.backtrace.join("\n\t")
|
|
268
|
-
ErrorType.new([["Internal error: #{ex}", call.position]])
|
|
269
|
-
end
|
|
270
|
-
|
|
271
|
-
def _find_method_type(scope, target, name, argTypes, macroTypes, position)
|
|
272
|
-
if target.respond_to?(:isError) && target.isError
|
|
273
|
-
return target
|
|
274
|
-
end
|
|
275
|
-
type = BaseTypeFuture.new(nil)
|
|
276
|
-
target.find_method2(target, name, argTypes, macroTypes, target.meta?, scope) do |method|
|
|
277
|
-
if method.nil?
|
|
278
|
-
unless argTypes.any?{|t| t && t.isError && (type.resolved(t); true)}
|
|
279
|
-
type.resolved(ErrorType.new([
|
|
280
|
-
["Cannot find %s method %s(%s) on %s" %
|
|
281
|
-
[ target.meta? ? "static" : "instance",
|
|
282
|
-
name,
|
|
283
|
-
argTypes.map{|t| t ? t.full_name : "?"}.join(', '),
|
|
284
|
-
target.full_name], position]]))
|
|
285
|
-
end
|
|
286
|
-
elsif method.kind_of?(Exception)
|
|
287
|
-
type.resolved(ErrorType.new([[method.message, position]]))
|
|
288
|
-
else
|
|
289
|
-
result = method.return_type
|
|
290
|
-
|
|
291
|
-
# Handle generics.
|
|
292
|
-
begin
|
|
293
|
-
if name == 'new' and target.type_parameters
|
|
294
|
-
result = Mirah::JVM::Types::GenericType.new(result) # Upgrade to a generic type.
|
|
295
|
-
target.type_parameters.each do |var|
|
|
296
|
-
result.type_parameter_map.put(var.name, _build_generic_type_future(var.bounds, position))
|
|
297
|
-
end
|
|
298
|
-
|
|
299
|
-
genericParameterTypes = method.member.generic_parameter_types
|
|
300
|
-
if genericParameterTypes
|
|
301
|
-
genericParameterTypes.each_index do |i|
|
|
302
|
-
_handle_nested_generic_parameter(genericParameterTypes[i], argTypes[i], result.type_parameter_map, position)
|
|
303
|
-
end
|
|
304
|
-
end
|
|
305
|
-
elsif target.generic? && method.respond_to?(:member)
|
|
306
|
-
genericParameterTypes = method.member.generic_parameter_types
|
|
307
|
-
if genericParameterTypes
|
|
308
|
-
genericParameterTypes.each_index do |i|
|
|
309
|
-
_handle_nested_generic_parameter(genericParameterTypes[i], argTypes[i], target.type_parameter_map, position)
|
|
310
|
-
end
|
|
311
|
-
end
|
|
312
|
-
|
|
313
|
-
result = _handle_nested_generic_return(result, method.member.generic_return_type, target.type_parameter_map, position)
|
|
314
|
-
result.resolve if result.respond_to?(:resolve)
|
|
315
|
-
end
|
|
316
|
-
rescue => ex
|
|
317
|
-
Mirah.print_error("Error inferring generics: #{ex.message}", position)
|
|
318
|
-
log("Error inferring generics: #{ex.message}\n#{ex.backtrace.join("\n")}")
|
|
319
|
-
result = method.return_type
|
|
320
|
-
end
|
|
321
|
-
|
|
322
|
-
if result.kind_of?(TypeFuture)
|
|
323
|
-
if result.isResolved
|
|
324
|
-
type.resolved(result.resolve)
|
|
325
|
-
else
|
|
326
|
-
result.onUpdate {|x, resolved| type.resolved(resolved) }
|
|
327
|
-
end
|
|
328
|
-
else
|
|
329
|
-
type.resolved(result)
|
|
330
|
-
end
|
|
331
|
-
|
|
332
|
-
# TODO(shepheb): This is modifying the argTypes of _find_method_type, and it shouldn't be.
|
|
333
|
-
# Moved to the bottom so the generics code above can access the original argTypes that were passed to _find_method_type.
|
|
334
|
-
argTypes = method.argument_types
|
|
335
|
-
end
|
|
336
|
-
end
|
|
337
|
-
argTypes = argTypes.map do |t|
|
|
338
|
-
if t.nil?
|
|
339
|
-
t
|
|
340
|
-
elsif t.isBlock
|
|
341
|
-
type.position_set(position) if (position && type.position.nil?)
|
|
342
|
-
# This should only happen if type is an error.
|
|
343
|
-
type.resolve
|
|
344
|
-
else
|
|
345
|
-
t
|
|
346
|
-
end
|
|
347
|
-
end
|
|
348
|
-
return_type = AssignableTypeFuture.new(nil)
|
|
349
|
-
return_type.assign(type, position)
|
|
350
|
-
MethodFuture.new(name, argTypes, return_type, false, position)
|
|
351
|
-
end
|
|
352
|
-
|
|
353
|
-
def _build_generic_type_future(bounds, position)
|
|
354
|
-
typeName = "java.lang.Object"
|
|
355
|
-
if bounds.size > 1
|
|
356
|
-
raise ArgumentError, "Multiple bounds on type variables are not supported."
|
|
357
|
-
elsif bounds.size == 1
|
|
358
|
-
typeName = bounds[0].raw_type.getClassName
|
|
359
|
-
end
|
|
360
|
-
GenericTypeFuture.new(position, type(nil, typeName))
|
|
361
|
-
end
|
|
362
|
-
|
|
363
|
-
def _handle_nested_generic_parameter(expectedType, providedType, type_parameter_map, position)
|
|
364
|
-
if expectedType.kind_of?(BiteScript::ASM::TypeVariable)
|
|
365
|
-
gtf = type_parameter_map.get(expectedType.name)
|
|
366
|
-
gtf.assign(SimpleFuture.new(providedType), position)
|
|
367
|
-
elsif expectedType.kind_of?(BiteScript::ASM::Wildcard) && providedType.kind_of?(TypeFuture)
|
|
368
|
-
# TODO(shepheb): Handle bounds here.
|
|
369
|
-
gtf = type_parameter_map.get(expectedType.upper_bound.name)
|
|
370
|
-
gtf.assign(providedType, position)
|
|
371
|
-
elsif expectedType.kind_of?(BiteScript::ASM::ParameterizedType)
|
|
372
|
-
# We can assume assignable_from? here, or this method would not have been called.
|
|
373
|
-
expectedParameters = expectedType.type_arguments
|
|
374
|
-
# Look up the values of the provided type's parameters.
|
|
375
|
-
providedParameters = providedType.type_parameters.map do |var|
|
|
376
|
-
if providedType.generic?
|
|
377
|
-
providedType.type_parameter_map.get(var.name)
|
|
378
|
-
else
|
|
379
|
-
type_parameter_map.get(var.name)
|
|
380
|
-
end
|
|
381
|
-
end
|
|
382
|
-
|
|
383
|
-
if expectedParameters && providedParameters && expectedParameters.size == providedParameters.size
|
|
384
|
-
expectedParameters.each_index do |i|
|
|
385
|
-
_handle_nested_generic_parameter(expectedParameters[i], providedParameters[i], type_parameter_map, position)
|
|
386
|
-
end
|
|
387
|
-
else
|
|
388
|
-
raise ArgumentError, "Type parameter mismatch: Expected #{expectedParameters}, found #{providedParameters}."
|
|
389
|
-
end
|
|
390
|
-
end
|
|
391
|
-
end
|
|
392
|
-
|
|
393
|
-
# TODO(shepheb): Handles only one level of nesting, it should handle arbitrary depth by recursion.
|
|
394
|
-
def _handle_nested_generic_return(returnType, genericReturnType, type_parameter_map, position)
|
|
395
|
-
if genericReturnType.kind_of?(BiteScript::ASM::TypeVariable)
|
|
396
|
-
type_parameter_map.get(genericReturnType.name)
|
|
397
|
-
elsif genericReturnType.kind_of?(BiteScript::ASM::ParameterizedType)
|
|
398
|
-
returnType = GenericType.new(returnType)
|
|
399
|
-
expectedTypeParameters = returnType.jvm_type.type_parameters
|
|
400
|
-
providedTypeParameters = genericReturnType.type_arguments
|
|
401
|
-
if expectedTypeParameters && providedTypeParameters && expectedTypeParameters.size == providedTypeParameters.size
|
|
402
|
-
expectedTypeParameters.each_index do |i|
|
|
403
|
-
returnType.type_parameter_map.put(expectedTypeParameters[i].name, type_parameter_map.get(providedTypeParameters[i].name))
|
|
404
|
-
end
|
|
405
|
-
else
|
|
406
|
-
raise ArgumentError, "Type parameter mismatch: Expected #{expectedTypeParameters}, found #{providedTypeParameters}"
|
|
407
|
-
end
|
|
408
|
-
returnType
|
|
409
|
-
else
|
|
410
|
-
returnType
|
|
411
|
-
end
|
|
412
|
-
end
|
|
413
|
-
|
|
414
|
-
def getMethodDefType(target, name, argTypes, returnType, position)
|
|
415
|
-
if target.nil?
|
|
416
|
-
return ErrorType.new([["No target", position]])
|
|
417
|
-
end
|
|
418
|
-
unless argTypes.all? {|a| a.hasDeclaration}
|
|
419
|
-
infer_override_args(target, name, argTypes)
|
|
420
|
-
end
|
|
421
|
-
if returnType.nil?
|
|
422
|
-
returnType = infer_override_return_type(target, name, argTypes)
|
|
423
|
-
end
|
|
424
|
-
|
|
425
|
-
args = argTypes.map {|a| a.resolve}
|
|
426
|
-
target = target.resolve
|
|
427
|
-
type = _find_method_type(nil, target, name, args, nil, position)
|
|
428
|
-
type.onUpdate do |m, resolved|
|
|
429
|
-
_declare_method(target, name, args, type)
|
|
430
|
-
end
|
|
431
|
-
|
|
432
|
-
args.each_with_index do |arg, i|
|
|
433
|
-
if arg.isError
|
|
434
|
-
argTypes[i].onUpdate do |x, resolved|
|
|
435
|
-
args[i] = resolved
|
|
436
|
-
_declare_method(target, name, args, type)
|
|
437
|
-
end
|
|
438
|
-
end
|
|
439
|
-
end
|
|
440
|
-
|
|
441
|
-
if type.kind_of?(ErrorType)
|
|
442
|
-
puts "Got error type for method #{name} on #{target.resolve} (#{target.resolve.class})"
|
|
443
|
-
position = type.position rescue nil
|
|
444
|
-
return_type = AssignableTypeFuture.new(position)
|
|
445
|
-
return_type.declare(type, position)
|
|
446
|
-
type = MethodFuture.new(name, args, return_type, false, position)
|
|
447
|
-
elsif returnType
|
|
448
|
-
type.returnType.declare(returnType, position)
|
|
449
|
-
end
|
|
450
|
-
|
|
451
|
-
type.to_java(MethodFuture)
|
|
452
|
-
rescue => ex
|
|
453
|
-
target_name = target.respond_to?(:name) ? target.name : target.resolve.name
|
|
454
|
-
error("Error getting method def type #{target_name}.#{name}: #{ex.message}\n#{ex.backtrace.join("\n\t")}")
|
|
455
|
-
return_type = AssignableTypeFuture.new(nil)
|
|
456
|
-
return_type.declare(ErrorType.new([["Internal error: #{ex}"]]), nil)
|
|
457
|
-
MethodFuture.new(name, [], return_type, false, nil)
|
|
458
|
-
end
|
|
459
|
-
|
|
460
|
-
def _declare_method(target, name, args, type)
|
|
461
|
-
return if args.any? {|a| a.isError }
|
|
462
|
-
return unless type.kind_of?(MethodFuture) && type.returnType.isResolved
|
|
463
|
-
resolved = type.returnType.resolve
|
|
464
|
-
resolved = resolved.returnType if resolved.respond_to?(:returnType)
|
|
465
|
-
log "Learned {0} method {1}.{2}({3}) = {4}", [
|
|
466
|
-
target.meta? ? "static" : "instance",
|
|
467
|
-
target.full_name,
|
|
468
|
-
name,
|
|
469
|
-
args.map{|a| a.full_name}.join(', '),
|
|
470
|
-
resolved.full_name].to_java
|
|
471
|
-
rewritten_name = name.sub(/=$/, '_set')
|
|
472
|
-
if target.meta?
|
|
473
|
-
target.unmeta.declare_static_method(rewritten_name, args, resolved, [])
|
|
474
|
-
else
|
|
475
|
-
target.declare_method(rewritten_name, args, resolved, [])
|
|
476
|
-
end
|
|
477
|
-
end
|
|
478
|
-
|
|
479
|
-
def getFieldType(target, name, position)
|
|
480
|
-
# This is currently only used for fields in the current class
|
|
481
|
-
klass = target.resolve
|
|
482
|
-
key = [klass, name]
|
|
483
|
-
t = @fields[key]
|
|
484
|
-
unless t
|
|
485
|
-
t = AssignableTypeFuture.new(position)
|
|
486
|
-
@fields[key] = t
|
|
487
|
-
t.on_update {|x, resolved| klass.unmeta.declare_field(name, resolved, klass.meta?)}
|
|
488
|
-
end
|
|
489
|
-
t
|
|
490
|
-
end
|
|
491
|
-
|
|
492
|
-
def getMainType(scope, script)
|
|
493
|
-
filename = File.basename(script.position.source.name || 'DashE')
|
|
494
|
-
classname = Mirah::JVM::Compiler::JVMBytecode.classname_from_filename(filename)
|
|
495
|
-
getMetaType(cache_and_wrap(declare_type(scope, classname)))
|
|
496
|
-
end
|
|
497
|
-
|
|
498
|
-
def defineType(scope, node, name, superclass, interfaces)
|
|
499
|
-
# TODO what if superclass or interfaces change later?
|
|
500
|
-
log("Defining type #{name} < #{superclass.resolve.name if superclass} #{interfaces.map{|i|i.resolve.name}.inspect}")
|
|
501
|
-
type = define_type(scope, node)
|
|
502
|
-
future = @futures[type.name]
|
|
503
|
-
if future
|
|
504
|
-
future.resolved(type)
|
|
505
|
-
future
|
|
506
|
-
else
|
|
507
|
-
cache_and_wrap(type)
|
|
508
|
-
end
|
|
509
|
-
rescue => ex
|
|
510
|
-
Mirah.print_error("Error defining type #{name}: #{ex.message}", node.position)
|
|
511
|
-
puts ex.backtrace.join("\n\t")
|
|
512
|
-
ErrorType.new([["Internal error: #{ex}", node.position]])
|
|
513
|
-
end
|
|
514
|
-
|
|
515
|
-
def addMacro(klass, macro)
|
|
516
|
-
klass.unmeta.add_compiled_macro(macro)
|
|
517
|
-
end
|
|
518
|
-
|
|
519
|
-
def extendClass(classname, extensions)
|
|
520
|
-
get_type(classname).load_extensions(extensions)
|
|
521
|
-
end
|
|
522
|
-
|
|
523
|
-
def infer_override_args(target, name, arg_types)
|
|
524
|
-
# TODO What if the method we're overriding hasn't been inferred yet?
|
|
525
|
-
log("Infering argument types for #{name}")
|
|
526
|
-
by_name = target.resolve.find_callable_methods(name, true)
|
|
527
|
-
by_name_and_arity = by_name.select {|m| m.argument_types.size == arg_types.size}
|
|
528
|
-
filtered_args = Set.new(by_name_and_arity.map {|m| m.argument_types})
|
|
529
|
-
if filtered_args.size == 1
|
|
530
|
-
arg_types.zip(filtered_args.first).each do |arg, super_arg|
|
|
531
|
-
arg.declare(cache_and_wrap(super_arg), arg.position)
|
|
532
|
-
end
|
|
533
|
-
else
|
|
534
|
-
log("Found method types:")
|
|
535
|
-
filtered_args.each {|args| log(" #{args.map{|a|a.full_name}.inspect}")}
|
|
536
|
-
arg_types.each {|arg| arg.declare(ErrorType.new([["Missing declaration"]]), nil)}
|
|
537
|
-
# TODO else give a more useful error?
|
|
538
|
-
end
|
|
539
|
-
end
|
|
540
|
-
|
|
541
|
-
def infer_override_return_type(target, name, arg_types)
|
|
542
|
-
by_name = target.resolve.find_callable_methods(name, true)
|
|
543
|
-
by_name_and_arity = {}
|
|
544
|
-
by_name.each {|m| by_name_and_arity[m.argument_types] = m if m.argument_types.size == arg_types.size }
|
|
545
|
-
resolved_args = arg_types.map {|a| a.resolve}
|
|
546
|
-
match = by_name_and_arity[resolved_args]
|
|
547
|
-
return cache_and_wrap(match.return_type) if match
|
|
548
|
-
end
|
|
549
|
-
|
|
550
|
-
def define_types(builder)
|
|
551
|
-
@declarations.each do |declaration|
|
|
552
|
-
declaration.define(builder)
|
|
553
|
-
end
|
|
554
|
-
end
|
|
555
|
-
|
|
556
|
-
def type(scope, name, array=false, meta=false)
|
|
557
|
-
if name.kind_of?(BiteScript::ASM::Type)
|
|
558
|
-
if name.getDescriptor[0] == ?[
|
|
559
|
-
return type(scope, name.getElementType, true, meta)
|
|
560
|
-
else
|
|
561
|
-
name = name.getClassName
|
|
562
|
-
end
|
|
563
|
-
elsif name.kind_of?(Type) && name.array?
|
|
564
|
-
array = true
|
|
565
|
-
end
|
|
566
|
-
type = basic_type(scope, name)
|
|
567
|
-
type = type.array_type if type && array
|
|
568
|
-
type = type.meta if type && meta
|
|
569
|
-
return type
|
|
570
|
-
end
|
|
571
|
-
|
|
572
|
-
def basic_type(scope, name)
|
|
573
|
-
if name.kind_of?(Type) || name.kind_of?(NarrowingType)
|
|
574
|
-
return name.basic_type
|
|
575
|
-
end
|
|
576
|
-
orig = name
|
|
577
|
-
if name.kind_of? Java::JavaClass
|
|
578
|
-
#TODO is is possible to get here anymore?
|
|
579
|
-
if name.array?
|
|
580
|
-
return type(scope, name.component_type, true)
|
|
581
|
-
else
|
|
582
|
-
name = name.name
|
|
583
|
-
end
|
|
584
|
-
elsif name.respond_to? :java_class
|
|
585
|
-
name = name.java_class.name
|
|
586
|
-
end
|
|
587
|
-
name = name.to_s unless name.kind_of?(::String)
|
|
588
|
-
raise ArgumentError, "Bad Type #{orig}" if name =~ /Java::/
|
|
589
|
-
raise ArgumentError, "Bad Type #{orig.inspect}" if name == '' || name.nil?
|
|
590
|
-
find_type(scope, name)
|
|
591
|
-
end
|
|
592
|
-
|
|
593
|
-
def find_type(scope, name)
|
|
594
|
-
type = get_type(name)
|
|
595
|
-
return type if type
|
|
596
|
-
|
|
597
|
-
if scope
|
|
598
|
-
imports = scope.imports
|
|
599
|
-
if imports.include?(name)
|
|
600
|
-
name = imports[name] while imports.include?(name)
|
|
601
|
-
type = get_type(name)
|
|
602
|
-
return type if type
|
|
603
|
-
end
|
|
604
|
-
|
|
605
|
-
# TODO support inner class names
|
|
606
|
-
if name !~ /\./
|
|
607
|
-
return package_search(name, scope)
|
|
608
|
-
end
|
|
609
|
-
end
|
|
610
|
-
return nil
|
|
611
|
-
end
|
|
612
|
-
|
|
613
|
-
def package_search(name, scope)
|
|
614
|
-
packages = []
|
|
615
|
-
current_package = scope.package
|
|
616
|
-
packages << current_package unless current_package.nil? || current_package.empty?
|
|
617
|
-
packages.concat(scope.search_packages)
|
|
618
|
-
packages << 'java.lang'
|
|
619
|
-
packages.each do |package|
|
|
620
|
-
type = get_type("#{package}.#{name}")
|
|
621
|
-
return type if type
|
|
622
|
-
end
|
|
623
|
-
return nil
|
|
624
|
-
end
|
|
625
|
-
|
|
626
|
-
def getBlockType
|
|
627
|
-
@block_type ||= BlockType.new
|
|
628
|
-
end
|
|
629
|
-
|
|
630
|
-
def get_type(full_name)
|
|
631
|
-
type = @known_types[full_name]
|
|
632
|
-
return type.basic_type if type
|
|
633
|
-
mirror = get_mirror(full_name)
|
|
634
|
-
unless mirror
|
|
635
|
-
if full_name =~ /^(.+)\.([^.]+)/
|
|
636
|
-
outer_name = $1
|
|
637
|
-
inner_name = $2
|
|
638
|
-
outer_type = get_type(outer_name)
|
|
639
|
-
return nil unless outer_type
|
|
640
|
-
full_name = "#{outer_type.name}$#{inner_name}"
|
|
641
|
-
mirror = get_mirror(full_name)
|
|
642
|
-
return nil unless mirror
|
|
643
|
-
else
|
|
644
|
-
return nil
|
|
645
|
-
end
|
|
646
|
-
end
|
|
647
|
-
type = Type.new(self, mirror).load_extensions
|
|
648
|
-
if full_name.include? '$'
|
|
649
|
-
@known_types[full_name.gsub('$', '.')] = type
|
|
650
|
-
end
|
|
651
|
-
@known_types[full_name] = type
|
|
652
|
-
end
|
|
653
|
-
|
|
654
|
-
def known_type(scope, name)
|
|
655
|
-
basic_type(scope, name)
|
|
656
|
-
end
|
|
657
|
-
|
|
658
|
-
def declare_type(scope, name)
|
|
659
|
-
full_name = name
|
|
660
|
-
package = scope.package
|
|
661
|
-
if !name.include?('.')
|
|
662
|
-
if package && !package.empty?
|
|
663
|
-
full_name = "#{package}.#{name}"
|
|
664
|
-
else
|
|
665
|
-
scope.on_package_change do
|
|
666
|
-
full_name = "#{scope.package}.#{name}"
|
|
667
|
-
scope.import(full_name, name)
|
|
668
|
-
@known_types[full_name] = @known_types[name]
|
|
669
|
-
end
|
|
670
|
-
end
|
|
671
|
-
end
|
|
672
|
-
if @known_types.include? full_name
|
|
673
|
-
@known_types[full_name]
|
|
674
|
-
else
|
|
675
|
-
scope.import(full_name, name)
|
|
676
|
-
@known_types[full_name] = TypeDefinition.new(self, scope, full_name, nil)
|
|
677
|
-
end
|
|
678
|
-
end
|
|
679
|
-
|
|
680
|
-
def define_type(scope, node)
|
|
681
|
-
if node.name.nil?
|
|
682
|
-
outer_node = node.find_ancestor {|n| (n != node && n.kind_of?(ClassDefinition)) || n.kind_of?(Script)}
|
|
683
|
-
if outer_node.kind_of?(ClassDefinition)
|
|
684
|
-
outer_name = outer_node.name.identifier
|
|
685
|
-
else
|
|
686
|
-
outer_name = Mirah::JVM::Compiler::JVMBytecode.classname_from_filename(node.position.source.name || 'DashE')
|
|
687
|
-
end
|
|
688
|
-
id = (@anonymous_classes[outer_name] += 1)
|
|
689
|
-
node.name_set(SimpleString.new("#{outer_name}$#{id}"))
|
|
690
|
-
end
|
|
691
|
-
name = node.name.identifier
|
|
692
|
-
full_name = name
|
|
693
|
-
package = scope.package
|
|
694
|
-
if !name.include?('.') && package && !package.empty?
|
|
695
|
-
full_name = "#{package}.#{name}"
|
|
696
|
-
end
|
|
697
|
-
if @known_types.include?(full_name) && @known_types[full_name].kind_of?(TypeDefinition)
|
|
698
|
-
existing = @known_types[full_name]
|
|
699
|
-
unless existing.node
|
|
700
|
-
existing.node = node
|
|
701
|
-
existing.scope = scope
|
|
702
|
-
end
|
|
703
|
-
existing
|
|
704
|
-
else
|
|
705
|
-
if InterfaceDeclaration === node
|
|
706
|
-
klass = InterfaceDefinition
|
|
707
|
-
else
|
|
708
|
-
klass = TypeDefinition
|
|
709
|
-
end
|
|
710
|
-
scope.import(full_name, name)
|
|
711
|
-
@known_types[full_name] = klass.new(self, scope, full_name, node)
|
|
712
|
-
end
|
|
713
|
-
end
|
|
714
|
-
|
|
715
|
-
def base_classpath
|
|
716
|
-
if __FILE__.include? '.jar'
|
|
717
|
-
Mirah::Env.encode_paths([__FILE__.split('!').first.split(Mirah::Env.path_separator).last])
|
|
718
|
-
else
|
|
719
|
-
Mirah::Env.encode_paths(['.',
|
|
720
|
-
File.dirname(__FILE__) + '/../../../../javalib/mirah-builtins.jar',
|
|
721
|
-
File.dirname(__FILE__) + '/../../../../javalib/mirah-parser.jar',
|
|
722
|
-
File.dirname(__FILE__) + '/../../../../javalib/mirah-bootstrap.jar'])
|
|
723
|
-
end
|
|
724
|
-
end
|
|
725
|
-
|
|
726
|
-
def classpath
|
|
727
|
-
@classpath ||= base_classpath
|
|
728
|
-
end
|
|
729
|
-
|
|
730
|
-
def classpath=(classpath)
|
|
731
|
-
if classpath
|
|
732
|
-
@classpath = Mirah::Env.encode_paths [classpath, base_classpath]
|
|
733
|
-
end
|
|
734
|
-
@resource_loader = nil
|
|
735
|
-
end
|
|
736
|
-
|
|
737
|
-
def resource_loader
|
|
738
|
-
@resource_loader ||= URLClassLoader.new(Mirah::Env.make_urls(classpath), bootstrap_loader)
|
|
739
|
-
end
|
|
740
|
-
|
|
741
|
-
def bootstrap_loader
|
|
742
|
-
@bootstrap_loader ||= begin
|
|
743
|
-
parent = if bootclasspath
|
|
744
|
-
Mirah::Util::IsolatedResourceLoader.new(Mirah::Env.make_urls(bootclasspath))
|
|
745
|
-
end
|
|
746
|
-
if __FILE__ =~ /^(file:.+jar)!/
|
|
747
|
-
bootstrap_urls = [java.net.URL.new($1)].to_java(java.net.URL)
|
|
748
|
-
else
|
|
749
|
-
bootstrap_jar = File.expand_path("#{__FILE__}/../../../../../javalib/mirah-bootstrap.jar")
|
|
750
|
-
bootstrap_urls = [java.io.File.new(bootstrap_jar).to_uri.to_url].to_java(java.net.URL)
|
|
751
|
-
end
|
|
752
|
-
URLClassLoader.new(bootstrap_urls, parent)
|
|
753
|
-
end
|
|
754
|
-
end
|
|
755
|
-
|
|
756
|
-
def bootclasspath=(classpath)
|
|
757
|
-
@bootclasspath = classpath
|
|
758
|
-
@bootstrap_loader = nil
|
|
759
|
-
@resource_loader = nil
|
|
760
|
-
end
|
|
761
|
-
|
|
762
|
-
attr_reader :bootclasspath
|
|
763
|
-
|
|
764
|
-
def mirror_class(klass)
|
|
765
|
-
name = klass.name.tr('.', '/')
|
|
766
|
-
if klass.respond_to?(:resource_as_stream)
|
|
767
|
-
stream = klass.resource_as_stream("/#{name}.class")
|
|
768
|
-
elsif klass.respond_to?(:get_resource_as_stream)
|
|
769
|
-
stream = klass.get_resource_as_stream("/#{name}.class")
|
|
770
|
-
else
|
|
771
|
-
return get_mirror(klass.name)
|
|
772
|
-
end
|
|
773
|
-
BiteScript::ASM::ClassMirror.load(stream)
|
|
774
|
-
end
|
|
775
|
-
|
|
776
|
-
def get_mirror(name)
|
|
777
|
-
@mirrors[name] ||= begin
|
|
778
|
-
classname = name.tr('.', '/')
|
|
779
|
-
stream = resource_loader.getResourceAsStream(classname + ".class")
|
|
780
|
-
if stream
|
|
781
|
-
mirror = BiteScript::ASM::ClassMirror.load(stream)
|
|
782
|
-
mirror if mirror.type.class_name == name
|
|
783
|
-
else
|
|
784
|
-
# TODO(ribrdb) Should this use a separate sourcepath?
|
|
785
|
-
url = resource_loader.getResource(classname + ".java")
|
|
786
|
-
if url
|
|
787
|
-
file = java.io.File.new(url.toURI)
|
|
788
|
-
mirrors = JavaSourceMirror.load(file, self) rescue []
|
|
789
|
-
mirrors.each do |mirror|
|
|
790
|
-
@mirrors[mirror.type.class_name] = mirror
|
|
791
|
-
end if mirrors
|
|
792
|
-
@mirrors[name]
|
|
793
|
-
end
|
|
794
|
-
end
|
|
795
|
-
end
|
|
796
|
-
end
|
|
797
|
-
|
|
798
|
-
def getAbstractMethods(type)
|
|
799
|
-
methods = []
|
|
800
|
-
unless type.isError
|
|
801
|
-
object = get_type("java.lang.Object")
|
|
802
|
-
interfaces = [type]
|
|
803
|
-
until interfaces.empty?
|
|
804
|
-
interface = interfaces.pop
|
|
805
|
-
abstract_methods = interface.declared_instance_methods.select {|m| m.abstract?}
|
|
806
|
-
methods += abstract_methods.select do |m|
|
|
807
|
-
begin
|
|
808
|
-
# Skip methods defined on Object
|
|
809
|
-
object.java_method(m.name, *m.argument_types)
|
|
810
|
-
false
|
|
811
|
-
rescue NameError
|
|
812
|
-
true
|
|
813
|
-
end
|
|
814
|
-
end
|
|
815
|
-
interfaces.concat(interface.interfaces)
|
|
816
|
-
end
|
|
817
|
-
# TODO ensure this works with hierarchies of abstract classes
|
|
818
|
-
# reject the methods implemented by the abstract class
|
|
819
|
-
if type.abstract?
|
|
820
|
-
implemented_methods = type.declared_instance_methods.reject{|m| m.abstract?}.map { |m| [m.name, m.argument_types, m.return_type] }
|
|
821
|
-
methods = methods.reject{|m| implemented_methods.include? [m.name, m.argument_types, m.return_type] }
|
|
822
|
-
end
|
|
823
|
-
end
|
|
824
|
-
methods.map do |method|
|
|
825
|
-
MethodType.new(method.name, method.argument_types, method.return_type, false)
|
|
826
|
-
end
|
|
827
|
-
end
|
|
828
|
-
end
|
|
829
|
-
end
|
|
830
|
-
require 'mirah/jvm/types/basic_types'
|