mirah 0.1.0.pre-java → 0.1.1-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.
- data/History.txt +736 -0
- data/README.md +71 -0
- data/Rakefile +227 -73
- data/examples/Fib.class +0 -0
- data/examples/macros/{string-each-char.mirah → string_each_char.mirah} +2 -3
- data/examples/simple_class.mirah +3 -3
- data/examples/{dynamic.mirah → simple_class.mirah~} +7 -12
- data/javalib/mirah-bootstrap.jar +0 -0
- data/javalib/mirah-builtins.jar +0 -0
- data/javalib/mirah-compiler.jar +0 -0
- data/javalib/mirah-parser.jar +0 -0
- data/javalib/mirah-util.jar +0 -0
- data/lib/mirah.rb +8 -1
- data/lib/mirah/ast.rb +1 -1
- data/lib/mirah/ast/scope.rb +16 -0
- data/lib/mirah/commands/base.rb +1 -3
- data/lib/mirah/compiler.rb +17 -3
- data/lib/mirah/errors.rb +10 -10
- data/lib/mirah/generator.rb +21 -9
- data/lib/mirah/jvm/compiler.rb +17 -0
- data/lib/mirah/jvm/compiler/base.rb +24 -5
- data/lib/mirah/jvm/compiler/jvm_bytecode.rb +83 -20
- data/lib/mirah/jvm/method_lookup.rb +43 -22
- data/lib/mirah/jvm/types.rb +1 -2
- data/lib/mirah/jvm/types/array_type.rb +1 -6
- data/lib/mirah/jvm/types/ast_ext.rb +31 -0
- data/lib/mirah/jvm/types/basic_types.rb +1 -2
- data/lib/mirah/jvm/types/boolean.rb +11 -10
- data/lib/mirah/jvm/types/extensions.rb +14 -5
- data/lib/mirah/jvm/types/factory.rb +128 -43
- data/lib/mirah/jvm/types/floats.rb +8 -10
- data/lib/mirah/jvm/types/integers.rb +16 -9
- data/lib/mirah/jvm/types/intrinsics.rb +17 -69
- data/lib/mirah/jvm/types/meta_type.rb +5 -0
- data/lib/mirah/jvm/types/methods.rb +317 -151
- data/lib/mirah/jvm/types/methods.rb~ +973 -0
- data/lib/mirah/jvm/types/number.rb +29 -6
- data/lib/mirah/jvm/types/primitive_type.rb +35 -7
- data/lib/mirah/jvm/types/source_mirror.rb +11 -6
- data/lib/mirah/jvm/types/type.rb +52 -0
- data/lib/mirah/jvm/types/type_definition.rb +8 -2
- data/lib/mirah/transform/ast_ext.rb +9 -31
- data/lib/mirah/transform/transformer.rb +1 -1
- data/lib/mirah/typer.rb +2 -1
- data/lib/mirah/util/argument_processor.rb +10 -14
- data/lib/mirah/util/argument_processor.rb~ +146 -0
- data/lib/mirah/util/compilation_state.rb +15 -9
- data/lib/mirah/util/process_errors.rb +8 -2
- data/lib/mirah/version.rb +2 -2
- data/lib/mirah_task.rb +0 -7
- data/test/core/typer_test.rb +21 -13
- data/test/core/util/argument_processor_test.rb +19 -19
- data/test/core/util/class_loader_test.rb +19 -4
- data/test/core/util/compilation_state_test.rb +38 -0
- data/test/fixtures/org/foo/LowerCaseInnerClass$inner.class +0 -0
- data/test/fixtures/org/foo/LowerCaseInnerClass.class +0 -0
- data/test/fixtures/org/foo/LowerCaseInnerClass.java +7 -0
- data/test/jvm/blocks_test.rb +50 -29
- data/test/jvm/bytecode_test_helper.rb +71 -57
- data/test/jvm/cast_test.rb +162 -0
- data/test/jvm/constructors_test.rb +48 -0
- data/test/jvm/enumerable_test.rb +136 -7
- data/test/jvm/example_test.rb +39 -0
- data/test/jvm/factory_test.rb +6 -0
- data/test/jvm/generics_test.rb +0 -5
- data/test/jvm/import_test.rb +81 -0
- data/test/jvm/interface_test.rb +113 -0
- data/test/jvm/java_typer_test.rb +57 -11
- data/test/jvm/jvm_commands_test.rb +24 -0
- data/test/jvm/jvm_compiler_test.rb +186 -370
- data/test/jvm/macros_test.rb +67 -6
- data/test/jvm/main_method_test.rb +1 -1
- data/test/jvm/mirror_compilation_test_helper.rb +24 -0
- data/test/jvm/new_backend_test_helper.rb +25 -0
- data/test/jvm/rescue_test.rb +153 -18
- data/test/jvm/string_test.rb +41 -0
- data/test/jvm/varargs_test.rb +65 -0
- data/test/mirrors/base_type_test.rb +96 -0
- data/test/mirrors/bytecode_mirror_test.rb +86 -0
- data/test/mirrors/generics_test.rb +776 -0
- data/test/mirrors/member_test.rb +69 -0
- data/test/mirrors/method_lookup_test.rb +574 -0
- data/test/mirrors/mirrors_test.rb +562 -0
- data/test/mirrors/simple_async_mirror_loader_test.rb +110 -0
- data/test/mirrors/simple_mirror_loader_test.rb +104 -0
- data/test/test_helper.rb +2 -1
- metadata +244 -217
- data/README.txt +0 -59
- data/javalib/dynalink-0.2.jar +0 -0
- data/lib/mirah/jvm/typer.rb +0 -177
- data/lib/mirah/jvm/types/dynamic_type.rb +0 -45
- data/lib/mirah/jvm/types/unreachable_type.rb +0 -27
|
@@ -99,7 +99,7 @@ module Mirah
|
|
|
99
99
|
by_name = if constructor
|
|
100
100
|
mapped_type.unmeta.declared_constructors
|
|
101
101
|
elsif meta
|
|
102
|
-
mapped_type.
|
|
102
|
+
mapped_type.find_callable_static_methods(name)
|
|
103
103
|
else
|
|
104
104
|
mapped_type.find_callable_methods(name)
|
|
105
105
|
end
|
|
@@ -118,21 +118,27 @@ module Mirah
|
|
|
118
118
|
|
|
119
119
|
def find_jls2(mapped_type, name, mapped_params, meta, by_name, include_fields=true, scope=nil)
|
|
120
120
|
return nil if mapped_params.any? {|p| p.nil? || p.isError}
|
|
121
|
-
|
|
122
|
-
|
|
121
|
+
|
|
122
|
+
# filter by arity, varargs
|
|
123
|
+
by_name_and_arity = by_name.select {|m| m.argument_types.size == mapped_params.size }
|
|
123
124
|
|
|
124
125
|
phase1_methods = phase1(mapped_params, by_name_and_arity)
|
|
125
126
|
|
|
126
127
|
if phase1_methods.size > 1
|
|
127
128
|
method_list = phase1_methods.map do |m|
|
|
128
|
-
|
|
129
|
+
case m.member
|
|
130
|
+
when BiteScript::ASM::MethodMirror
|
|
131
|
+
m.member.inspect
|
|
132
|
+
else
|
|
133
|
+
"#{m.name}(#{m.parameter_types.map(&:name).join(', ')})"
|
|
134
|
+
end
|
|
129
135
|
end.join("\n")
|
|
130
136
|
raise "Ambiguous targets invoking #{mapped_type}.#{name}:\n#{method_list}"
|
|
131
137
|
end
|
|
132
138
|
|
|
133
139
|
phase1_methods[0] ||
|
|
134
140
|
phase2(mapped_params, by_name) ||
|
|
135
|
-
phase3(mapped_params, by_name) ||
|
|
141
|
+
phase3(mapped_params, by_name)[0] ||
|
|
136
142
|
(include_fields &&
|
|
137
143
|
(field_lookup(mapped_params, mapped_type, meta, name, scope) ||
|
|
138
144
|
inner_class(mapped_params, mapped_type, meta, name)))
|
|
@@ -152,15 +158,17 @@ module Mirah
|
|
|
152
158
|
end
|
|
153
159
|
|
|
154
160
|
# otherwise, check for potential match and compare to current
|
|
155
|
-
# TODO: missing ambiguity check; picks
|
|
161
|
+
# TODO: missing ambiguity check; picks first method of equal specificity
|
|
162
|
+
# Picking the first method means we prefer methods from the child class,
|
|
163
|
+
# which is important if the parent class is not accessible (like AbstractStringBuilder).
|
|
156
164
|
if each_is_exact_or_subtype_or_convertible(mapped_params, method_params)
|
|
157
|
-
if currents.
|
|
158
|
-
if is_more_specific?(
|
|
159
|
-
# potential is better, dump all currents
|
|
160
|
-
currents = [potential]
|
|
161
|
-
elsif is_more_specific?(currents[0].argument_types, potential.argument_types)
|
|
165
|
+
if !currents.empty?
|
|
166
|
+
if is_more_specific?(currents[0].argument_types, potential.argument_types)
|
|
162
167
|
# currents are better, try next potential
|
|
163
168
|
#next
|
|
169
|
+
elsif is_more_specific?(potential.argument_types, currents[0].argument_types)
|
|
170
|
+
# potential is better, dump all currents
|
|
171
|
+
currents = [potential]
|
|
164
172
|
else
|
|
165
173
|
# equal specificity, append to currents
|
|
166
174
|
currents << potential
|
|
@@ -186,7 +194,26 @@ module Mirah
|
|
|
186
194
|
end
|
|
187
195
|
|
|
188
196
|
def phase3(mapped_params, potentials)
|
|
189
|
-
|
|
197
|
+
potential_varargs = potentials.select{|m| m.respond_to?(:varargs?) && m.varargs? }
|
|
198
|
+
methods = potential_varargs.inject([]) do |currents, potential|
|
|
199
|
+
method_params = potential.argument_types
|
|
200
|
+
# match n-1 params of potential
|
|
201
|
+
non_varargs_params, possible_varargs_params = mapped_params.partition.with_index{|param,i| i < method_params.size-1}
|
|
202
|
+
|
|
203
|
+
vararg_types = possible_varargs_params.size.times.map{ method_params.last.component_type }
|
|
204
|
+
|
|
205
|
+
if each_is_exact(non_varargs_params, method_params[0..-2]) &&
|
|
206
|
+
each_is_exact(possible_varargs_params, vararg_types)
|
|
207
|
+
return [potential]
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
if each_is_exact_or_subtype_or_convertible(non_varargs_params, method_params[0..-2]) &&
|
|
211
|
+
each_is_exact_or_subtype_or_convertible(possible_varargs_params, vararg_types)
|
|
212
|
+
currents << potential
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
currents
|
|
216
|
+
end
|
|
190
217
|
end
|
|
191
218
|
|
|
192
219
|
def field_lookup(mapped_params, mapped_type, meta, name, scope)
|
|
@@ -234,24 +261,17 @@ module Mirah
|
|
|
234
261
|
end
|
|
235
262
|
|
|
236
263
|
def inner_class(params, type, meta, name)
|
|
237
|
-
return unless params.
|
|
264
|
+
return unless params.empty? && meta
|
|
238
265
|
log("Attempting inner class lookup for '#{name}' on #{type}")
|
|
239
266
|
type.inner_class_getter(name)
|
|
240
267
|
end
|
|
241
268
|
|
|
242
269
|
def each_is_exact(incoming, target)
|
|
243
|
-
incoming.
|
|
244
|
-
target_type = target[i]
|
|
245
|
-
|
|
246
|
-
# exact match
|
|
247
|
-
return false unless target_type == in_type
|
|
248
|
-
end
|
|
249
|
-
return true
|
|
270
|
+
incoming.zip(target).all? { |in_type, target_type| target_type == in_type }
|
|
250
271
|
end
|
|
251
272
|
|
|
252
273
|
def each_is_exact_or_subtype_or_convertible(incoming, target)
|
|
253
|
-
incoming.
|
|
254
|
-
target_type = target[i]
|
|
274
|
+
incoming.zip(target).each do |in_type, target_type|
|
|
255
275
|
|
|
256
276
|
# exact match
|
|
257
277
|
next if target_type == in_type
|
|
@@ -259,6 +279,7 @@ module Mirah
|
|
|
259
279
|
unless target_type.respond_to?(:primitive?) && in_type.respond_to?(:primitive?)
|
|
260
280
|
puts "Huh?"
|
|
261
281
|
end
|
|
282
|
+
|
|
262
283
|
# primitive is safely convertible
|
|
263
284
|
if target_type.primitive?
|
|
264
285
|
if in_type.primitive?
|
data/lib/mirah/jvm/types.rb
CHANGED
|
@@ -29,11 +29,9 @@ require 'mirah/jvm/types/meta_type'
|
|
|
29
29
|
require 'mirah/jvm/types/generic_type'
|
|
30
30
|
require 'mirah/jvm/types/null_type'
|
|
31
31
|
require 'mirah/jvm/types/implicit_nil_type'
|
|
32
|
-
require 'mirah/jvm/types/unreachable_type'
|
|
33
32
|
require 'mirah/jvm/types/void_type'
|
|
34
33
|
require 'mirah/jvm/types/block_type'
|
|
35
34
|
require 'mirah/jvm/types/array_type'
|
|
36
|
-
require 'mirah/jvm/types/dynamic_type'
|
|
37
35
|
require 'mirah/jvm/types/type_definition'
|
|
38
36
|
require 'mirah/jvm/types/interface_definition'
|
|
39
37
|
require 'mirah/jvm/types/intrinsics'
|
|
@@ -44,3 +42,4 @@ require 'mirah/jvm/types/boolean'
|
|
|
44
42
|
require 'mirah/jvm/types/floats'
|
|
45
43
|
require 'mirah/jvm/types/literals'
|
|
46
44
|
require 'mirah/jvm/types/factory'
|
|
45
|
+
require 'mirah/jvm/types/extensions'
|
|
@@ -6,12 +6,7 @@ module Mirah
|
|
|
6
6
|
|
|
7
7
|
def initialize(component_type)
|
|
8
8
|
@component_type = component_type
|
|
9
|
-
|
|
10
|
-
#@type = java.lang.reflect.Array.newInstance(@component_type.jvm_type, 0).class
|
|
11
|
-
else
|
|
12
|
-
# FIXME: THIS IS WRONG, but I don't know how to fix it
|
|
13
|
-
#@type = @component_type
|
|
14
|
-
end
|
|
9
|
+
|
|
15
10
|
@name = component_type.name
|
|
16
11
|
@type_system = component_type.type_system
|
|
17
12
|
self.intrinsics
|
|
@@ -0,0 +1,31 @@
|
|
|
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
|
+
class Java::MirahLangAst::NodeImpl
|
|
17
|
+
def annotated_abstract?
|
|
18
|
+
annotations.each do |anno|
|
|
19
|
+
if anno.type.typeref.name == 'org.mirah.jvm.types.Modifiers'
|
|
20
|
+
anno.values.each do |entry|
|
|
21
|
+
if entry.key.identifier == 'flags'
|
|
22
|
+
entry.value.values.each do |value|
|
|
23
|
+
return true if value.identifier == 'ABSTRACT'
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
false
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -19,7 +19,7 @@ module Mirah::JVM::Types
|
|
|
19
19
|
@known_types.update(
|
|
20
20
|
'boolean' => BooleanType.new(self, 'boolean', java.lang.Boolean),
|
|
21
21
|
'byte' => IntegerType.new(self, 'byte', java.lang.Byte),
|
|
22
|
-
'char' =>
|
|
22
|
+
'char' => CharacterType.new(self, 'char', java.lang.Character),
|
|
23
23
|
'short' => IntegerType.new(self, 'short', java.lang.Short),
|
|
24
24
|
'int' => IntegerType.new(self, 'int', java.lang.Integer),
|
|
25
25
|
'long' => LongType.new(self, 'long', java.lang.Long),
|
|
@@ -36,7 +36,6 @@ module Mirah::JVM::Types
|
|
|
36
36
|
@known_types['void'] = VoidType.new(self)
|
|
37
37
|
@known_types['null'] = NullType.new(self)
|
|
38
38
|
@known_types['implicit_nil'] = ImplicitNilType.new(self)
|
|
39
|
-
@known_types['dynamic'] = DynamicType.new(self)
|
|
40
39
|
end
|
|
41
40
|
end
|
|
42
41
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c) 2010 The Mirah project authors. All Rights Reserved.
|
|
1
|
+
# Copyright (c) 2010-2013 The Mirah project authors. All Rights Reserved.
|
|
2
2
|
# All contributing project authors may be found in the NOTICE file.
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -23,15 +23,6 @@ module Mirah::JVM::Types
|
|
|
23
23
|
'i'
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
-
def box(builder)
|
|
27
|
-
box_type = Mirah::AST::type(nil, 'java.lang.Boolean')
|
|
28
|
-
builder.invokestatic box_type, "valueOf", [box_type, self]
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def box_type
|
|
32
|
-
@type_system.type(nil, 'java.lang.Boolean')
|
|
33
|
-
end
|
|
34
|
-
|
|
35
26
|
def add_intrinsics
|
|
36
27
|
args = [math_type]
|
|
37
28
|
add_method('==', args, ComparisonIntrinsic.new(self, '==', :eq, args))
|
|
@@ -42,6 +33,16 @@ module Mirah::JVM::Types
|
|
|
42
33
|
@type_system.type(nil, 'boolean')
|
|
43
34
|
end
|
|
44
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
|
+
|
|
45
46
|
# same as NumberType's
|
|
46
47
|
def compile_boolean_operator(compiler, op, negated, call, label)
|
|
47
48
|
# Promote the target or the argument if necessary
|
|
@@ -62,22 +62,31 @@ module Mirah::JVM::Types
|
|
|
62
62
|
end
|
|
63
63
|
|
|
64
64
|
def declared_instance_methods(name=nil)
|
|
65
|
-
__combine_methods(__getobj__.declared_instance_methods)
|
|
65
|
+
__combine_methods(__getobj__.declared_instance_methods, name)
|
|
66
66
|
end
|
|
67
67
|
|
|
68
68
|
def declared_class_methods(name=nil)
|
|
69
|
-
__combine_methods(__getobj__.declared_class_methods)
|
|
69
|
+
__combine_methods(__getobj__.declared_class_methods, name)
|
|
70
70
|
end
|
|
71
71
|
|
|
72
|
-
def
|
|
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)
|
|
73
81
|
methods = {}
|
|
74
82
|
basic_methods.each do |method|
|
|
75
|
-
key = [method.name, method.
|
|
83
|
+
key = [method.name, method.argument_types, method.return_type]
|
|
76
84
|
methods[key] = method
|
|
77
85
|
end
|
|
78
86
|
@static_includes.each do |type|
|
|
79
87
|
type.declared_class_methods.each do |method|
|
|
80
|
-
|
|
88
|
+
next if name && method.name != name
|
|
89
|
+
key = [method.name, method.argument_types, method.return_type]
|
|
81
90
|
methods[key] ||= method
|
|
82
91
|
end
|
|
83
92
|
end
|
|
@@ -40,13 +40,8 @@ module Mirah::JVM::Types
|
|
|
40
40
|
begin
|
|
41
41
|
java_import 'org.mirah.builtins.Builtins'
|
|
42
42
|
rescue NameError
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
java_import 'org.mirah.builtins.Builtins'
|
|
46
|
-
rescue NameError
|
|
47
|
-
# We might be trying to compile mirah-builtins.jar, so just continue.
|
|
48
|
-
Builtins = nil
|
|
49
|
-
end
|
|
43
|
+
# We might be trying to compile mirah-builtins.jar, so just continue.
|
|
44
|
+
Builtins = nil
|
|
50
45
|
end
|
|
51
46
|
|
|
52
47
|
java_import 'java.net.URLClassLoader'
|
|
@@ -67,6 +62,7 @@ module Mirah::JVM::Types
|
|
|
67
62
|
@declarations = []
|
|
68
63
|
@mirrors = {}
|
|
69
64
|
@futures = {}
|
|
65
|
+
@fields = {}
|
|
70
66
|
create_basic_types
|
|
71
67
|
end
|
|
72
68
|
|
|
@@ -77,12 +73,13 @@ module Mirah::JVM::Types
|
|
|
77
73
|
end
|
|
78
74
|
@declarations = []
|
|
79
75
|
@futures = {}
|
|
76
|
+
@fields = {}
|
|
80
77
|
end
|
|
81
78
|
|
|
82
79
|
def maybe_initialize_builtins(compiler)
|
|
83
80
|
if Builtins
|
|
84
81
|
begin
|
|
85
|
-
Builtins.initialize_builtins(compiler)
|
|
82
|
+
Builtins.initialize_builtins(compiler.type_system)
|
|
86
83
|
rescue NativeException => ex
|
|
87
84
|
error("Error initializing builtins", ex.cause)
|
|
88
85
|
rescue => ex
|
|
@@ -102,6 +99,7 @@ module Mirah::JVM::Types
|
|
|
102
99
|
def cache_and_wrap(resolved_type)
|
|
103
100
|
@futures[resolved_type.name] ||= wrap(resolved_type)
|
|
104
101
|
end
|
|
102
|
+
|
|
105
103
|
def cache_and_wrap_type(name)
|
|
106
104
|
@futures[name] ||= begin
|
|
107
105
|
type = type(nil, name)
|
|
@@ -115,6 +113,7 @@ module Mirah::JVM::Types
|
|
|
115
113
|
def addDefaultImports(scope)
|
|
116
114
|
scope.import('java.lang.*', '*')
|
|
117
115
|
end
|
|
116
|
+
|
|
118
117
|
def getNullType; cache_and_wrap_type('null') end
|
|
119
118
|
def getImplicitNilType; cache_and_wrap_type('implicit_nil') end
|
|
120
119
|
def getVoidType; cache_and_wrap_type('void') end
|
|
@@ -166,6 +165,7 @@ module Mirah::JVM::Types
|
|
|
166
165
|
future
|
|
167
166
|
end
|
|
168
167
|
end
|
|
168
|
+
|
|
169
169
|
def getSuperClass(future)
|
|
170
170
|
superclass = BaseTypeFuture.new(nil)
|
|
171
171
|
future.on_update do |_, type|
|
|
@@ -173,6 +173,7 @@ module Mirah::JVM::Types
|
|
|
173
173
|
end
|
|
174
174
|
superclass
|
|
175
175
|
end
|
|
176
|
+
|
|
176
177
|
def getArrayType(type)
|
|
177
178
|
if type.kind_of?(Type)
|
|
178
179
|
type.array_type
|
|
@@ -182,6 +183,7 @@ module Mirah::JVM::Types
|
|
|
182
183
|
future
|
|
183
184
|
end
|
|
184
185
|
end
|
|
186
|
+
|
|
185
187
|
def box(type)
|
|
186
188
|
boxed = BaseTypeFuture.new(nil)
|
|
187
189
|
type.on_update do |_, resolved|
|
|
@@ -205,6 +207,7 @@ module Mirah::JVM::Types
|
|
|
205
207
|
log("Error inferring generics: #{ex.message}\n#{ex.backtrace.join("\n")}")
|
|
206
208
|
cache_and_wrap_type('java.util.List')
|
|
207
209
|
end
|
|
210
|
+
|
|
208
211
|
def getHashLiteralType(key_type, value_type, position)
|
|
209
212
|
result = Mirah::JVM::Types::GenericType.new(type(nil, 'java.util.HashMap')) # Upgrade to a generic type.
|
|
210
213
|
generic_key, generic_value = result.type_parameters
|
|
@@ -218,6 +221,7 @@ module Mirah::JVM::Types
|
|
|
218
221
|
log("Error inferring generics: #{ex.message}\n#{ex.backtrace.join("\n")}")
|
|
219
222
|
cache_and_wrap_type('java.util.HashMap')
|
|
220
223
|
end
|
|
224
|
+
|
|
221
225
|
def get(scope, typeref)
|
|
222
226
|
basic_type = if scope.nil?
|
|
223
227
|
cache_and_wrap_type(typeref.name)
|
|
@@ -246,6 +250,7 @@ module Mirah::JVM::Types
|
|
|
246
250
|
basic_type
|
|
247
251
|
end
|
|
248
252
|
end
|
|
253
|
+
|
|
249
254
|
def getLocalType(scope, name, position)
|
|
250
255
|
scope.local_type(name, position)
|
|
251
256
|
end
|
|
@@ -270,12 +275,14 @@ module Mirah::JVM::Types
|
|
|
270
275
|
type = BaseTypeFuture.new(nil)
|
|
271
276
|
target.find_method2(target, name, argTypes, macroTypes, target.meta?, scope) do |method|
|
|
272
277
|
if method.nil?
|
|
273
|
-
type.resolved(
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
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
|
|
279
286
|
elsif method.kind_of?(Exception)
|
|
280
287
|
type.resolved(ErrorType.new([[method.message, position]]))
|
|
281
288
|
else
|
|
@@ -404,38 +411,43 @@ module Mirah::JVM::Types
|
|
|
404
411
|
end
|
|
405
412
|
end
|
|
406
413
|
|
|
407
|
-
def getMethodDefType(target, name, argTypes)
|
|
414
|
+
def getMethodDefType(target, name, argTypes, returnType, position)
|
|
408
415
|
if target.nil?
|
|
409
|
-
return ErrorType.new([["No target"]])
|
|
416
|
+
return ErrorType.new([["No target", position]])
|
|
410
417
|
end
|
|
411
418
|
unless argTypes.all? {|a| a.hasDeclaration}
|
|
412
419
|
infer_override_args(target, name, argTypes)
|
|
413
420
|
end
|
|
421
|
+
if returnType.nil?
|
|
422
|
+
returnType = infer_override_return_type(target, name, argTypes)
|
|
423
|
+
end
|
|
424
|
+
|
|
414
425
|
args = argTypes.map {|a| a.resolve}
|
|
415
426
|
target = target.resolve
|
|
416
|
-
type = _find_method_type(nil, target, name, args, nil,
|
|
427
|
+
type = _find_method_type(nil, target, name, args, nil, position)
|
|
417
428
|
type.onUpdate do |m, resolved|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
target.unmeta.declare_static_method(rewritten_name, args, resolved, [])
|
|
428
|
-
else
|
|
429
|
-
target.declare_method(rewritten_name, args, resolved, []) unless target.isError
|
|
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
|
|
430
438
|
end
|
|
431
439
|
end
|
|
440
|
+
|
|
432
441
|
if type.kind_of?(ErrorType)
|
|
433
442
|
puts "Got error type for method #{name} on #{target.resolve} (#{target.resolve.class})"
|
|
434
443
|
position = type.position rescue nil
|
|
435
444
|
return_type = AssignableTypeFuture.new(position)
|
|
436
445
|
return_type.declare(type, position)
|
|
437
|
-
type = MethodFuture.new(name, args, return_type, false,
|
|
446
|
+
type = MethodFuture.new(name, args, return_type, false, position)
|
|
447
|
+
elsif returnType
|
|
448
|
+
type.returnType.declare(returnType, position)
|
|
438
449
|
end
|
|
450
|
+
|
|
439
451
|
type.to_java(MethodFuture)
|
|
440
452
|
rescue => ex
|
|
441
453
|
target_name = target.respond_to?(:name) ? target.name : target.resolve.name
|
|
@@ -444,13 +456,48 @@ module Mirah::JVM::Types
|
|
|
444
456
|
return_type.declare(ErrorType.new([["Internal error: #{ex}"]]), nil)
|
|
445
457
|
MethodFuture.new(name, [], return_type, false, nil)
|
|
446
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
|
+
|
|
447
492
|
def getMainType(scope, script)
|
|
448
493
|
filename = File.basename(script.position.source.name || 'DashE')
|
|
449
494
|
classname = Mirah::JVM::Compiler::JVMBytecode.classname_from_filename(filename)
|
|
450
495
|
getMetaType(cache_and_wrap(declare_type(scope, classname)))
|
|
451
496
|
end
|
|
497
|
+
|
|
452
498
|
def defineType(scope, node, name, superclass, interfaces)
|
|
453
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}")
|
|
454
501
|
type = define_type(scope, node)
|
|
455
502
|
future = @futures[type.name]
|
|
456
503
|
if future
|
|
@@ -468,6 +515,7 @@ module Mirah::JVM::Types
|
|
|
468
515
|
def addMacro(klass, macro)
|
|
469
516
|
klass.unmeta.add_compiled_macro(macro)
|
|
470
517
|
end
|
|
518
|
+
|
|
471
519
|
def extendClass(classname, extensions)
|
|
472
520
|
get_type(classname).load_extensions(extensions)
|
|
473
521
|
end
|
|
@@ -477,13 +525,27 @@ module Mirah::JVM::Types
|
|
|
477
525
|
log("Infering argument types for #{name}")
|
|
478
526
|
by_name = target.resolve.find_callable_methods(name, true)
|
|
479
527
|
by_name_and_arity = by_name.select {|m| m.argument_types.size == arg_types.size}
|
|
480
|
-
|
|
481
|
-
|
|
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|
|
|
482
531
|
arg.declare(cache_and_wrap(super_arg), arg.position)
|
|
483
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)}
|
|
484
537
|
# TODO else give a more useful error?
|
|
485
538
|
end
|
|
486
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
|
|
487
549
|
|
|
488
550
|
def define_types(builder)
|
|
489
551
|
@declarations.each do |declaration|
|
|
@@ -513,8 +575,9 @@ module Mirah::JVM::Types
|
|
|
513
575
|
end
|
|
514
576
|
orig = name
|
|
515
577
|
if name.kind_of? Java::JavaClass
|
|
578
|
+
#TODO is is possible to get here anymore?
|
|
516
579
|
if name.array?
|
|
517
|
-
return type(name.component_type, true)
|
|
580
|
+
return type(scope, name.component_type, true)
|
|
518
581
|
else
|
|
519
582
|
name = name.name
|
|
520
583
|
end
|
|
@@ -573,10 +636,10 @@ module Mirah::JVM::Types
|
|
|
573
636
|
outer_name = $1
|
|
574
637
|
inner_name = $2
|
|
575
638
|
outer_type = get_type(outer_name)
|
|
576
|
-
return nil
|
|
639
|
+
return nil unless outer_type
|
|
577
640
|
full_name = "#{outer_type.name}$#{inner_name}"
|
|
578
641
|
mirror = get_mirror(full_name)
|
|
579
|
-
return nil
|
|
642
|
+
return nil unless mirror
|
|
580
643
|
else
|
|
581
644
|
return nil
|
|
582
645
|
end
|
|
@@ -655,16 +718,25 @@ module Mirah::JVM::Types
|
|
|
655
718
|
end.to_java(java.net.URL)
|
|
656
719
|
end
|
|
657
720
|
|
|
721
|
+
def base_classpath
|
|
722
|
+
if __FILE__.include? '.jar'
|
|
723
|
+
Mirah::Env.encode_paths([__FILE__.split('!').first.split(':').last])
|
|
724
|
+
else
|
|
725
|
+
Mirah::Env.encode_paths(['.',
|
|
726
|
+
File.dirname(__FILE__) + '/../../../../javalib/mirah-builtins.jar',
|
|
727
|
+
File.dirname(__FILE__) + '/../../../../javalib/mirah-parser.jar',
|
|
728
|
+
File.dirname(__FILE__) + '/../../../../javalib/mirah-bootstrap.jar'])
|
|
729
|
+
end
|
|
730
|
+
end
|
|
731
|
+
|
|
658
732
|
def classpath
|
|
659
|
-
@classpath ||=
|
|
660
|
-
#TODO nh make this less hacked together.
|
|
661
|
-
File.dirname(__FILE__) + '/../../../../javalib/mirah-builtins.jar',
|
|
662
|
-
File.dirname(__FILE__) + '/../../../../javalib/mirah-parser.jar',
|
|
663
|
-
File.dirname(__FILE__) + '/../../../../javalib/mirah-bootstrap.jar'])
|
|
733
|
+
@classpath ||= base_classpath
|
|
664
734
|
end
|
|
665
735
|
|
|
666
736
|
def classpath=(classpath)
|
|
667
|
-
|
|
737
|
+
if classpath
|
|
738
|
+
@classpath = classpath + ":" + base_classpath
|
|
739
|
+
end
|
|
668
740
|
@resource_loader = nil
|
|
669
741
|
end
|
|
670
742
|
|
|
@@ -695,18 +767,31 @@ module Mirah::JVM::Types
|
|
|
695
767
|
|
|
696
768
|
attr_reader :bootclasspath
|
|
697
769
|
|
|
770
|
+
def mirror_class(klass)
|
|
771
|
+
name = klass.name.tr('.', '/')
|
|
772
|
+
if klass.respond_to?(:resource_as_stream)
|
|
773
|
+
stream = klass.resource_as_stream("/#{name}.class")
|
|
774
|
+
elsif klass.respond_to?(:get_resource_as_stream)
|
|
775
|
+
stream = klass.get_resource_as_stream("/#{name}.class")
|
|
776
|
+
else
|
|
777
|
+
return get_mirror(klass.name)
|
|
778
|
+
end
|
|
779
|
+
BiteScript::ASM::ClassMirror.load(stream)
|
|
780
|
+
end
|
|
781
|
+
|
|
698
782
|
def get_mirror(name)
|
|
699
783
|
@mirrors[name] ||= begin
|
|
700
784
|
classname = name.tr('.', '/')
|
|
701
785
|
stream = resource_loader.getResourceAsStream(classname + ".class")
|
|
702
786
|
if stream
|
|
703
|
-
BiteScript::ASM::ClassMirror.load(stream)
|
|
787
|
+
mirror = BiteScript::ASM::ClassMirror.load(stream)
|
|
788
|
+
mirror if mirror.type.class_name == name
|
|
704
789
|
else
|
|
705
790
|
# TODO(ribrdb) Should this use a separate sourcepath?
|
|
706
791
|
url = resource_loader.getResource(classname + ".java")
|
|
707
792
|
if url
|
|
708
793
|
file = java.io.File.new(url.toURI)
|
|
709
|
-
mirrors = JavaSourceMirror.load(file, self)
|
|
794
|
+
mirrors = JavaSourceMirror.load(file, self) rescue []
|
|
710
795
|
mirrors.each do |mirror|
|
|
711
796
|
@mirrors[mirror.type.class_name] = mirror
|
|
712
797
|
end if mirrors
|