mirah 0.1.2-java → 0.1.3-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/History.txt +225 -0
  3. data/Rakefile +108 -315
  4. data/TODO.md +100 -0
  5. data/bin/bundler +16 -0
  6. data/bin/rake +16 -0
  7. data/dist/mirahc.jar +0 -0
  8. data/examples/appengine/Readme +0 -1
  9. data/examples/literals.mirah +17 -0
  10. data/examples/macros/string_each_char.mirah +1 -1
  11. data/lib/mirah.rb +11 -21
  12. data/lib/mirah/transform/transformer.rb +1 -2
  13. data/lib/mirah/util/class_loader.rb +1 -1
  14. data/lib/mirah/util/logging.rb +0 -63
  15. data/lib/mirah/util/process_errors.rb +1 -0
  16. data/lib/mirah/version.rb +1 -1
  17. data/{examples/simple_class.mirah~ → test/artifacts/jar_test.rb} +7 -11
  18. data/{lib/mirah/commands.rb → test/artifacts/jruby_test.rb} +8 -5
  19. data/test/core/typer_test.rb +29 -11
  20. data/test/core/util/argument_processor_test.rb +24 -23
  21. data/test/core/util/class_loader_test.rb +7 -4
  22. data/test/core/util/{compilation_state_test.rb → jvm_version_test.rb} +20 -16
  23. data/test/fixtures/org/foo/ImplicitClassRetAnno.java +4 -0
  24. data/test/fixtures/org/foo/IntAnno.java +9 -0
  25. data/test/jvm/annotations_test.rb +11 -11
  26. data/test/jvm/blocks_test.rb +16 -12
  27. data/test/jvm/constructors_test.rb +8 -8
  28. data/test/jvm/enumerable_test.rb +48 -24
  29. data/test/jvm/generics_test.rb +3 -7
  30. data/test/jvm/import_test.rb +14 -0
  31. data/test/jvm/interface_test.rb +9 -24
  32. data/test/jvm/jvm_commands_test.rb +22 -4
  33. data/test/jvm/jvm_compiler_test.rb +124 -79
  34. data/test/jvm/list_extensions_test.rb +1 -1
  35. data/test/jvm/macros_test.rb +67 -14
  36. data/test/jvm/main_method_test.rb +1 -1
  37. data/test/jvm/new_backend_test_helper.rb +100 -3
  38. data/{lib/mirah/jvm/types/bitescript_ext.rb → test/jvm/static_fields_test.rb} +22 -21
  39. data/test/mirrors/base_type_test.rb +4 -3
  40. data/test/mirrors/bytecode_mirror_test.rb +35 -15
  41. data/test/mirrors/generics_test.rb +14 -5
  42. data/test/mirrors/member_test.rb +2 -1
  43. data/test/mirrors/method_lookup_test.rb +18 -6
  44. data/test/mirrors/mirrors_test.rb +87 -20
  45. data/test/mirrors/simple_async_mirror_loader_test.rb +7 -3
  46. data/test/mirrors/simple_mirror_loader_test.rb +5 -5
  47. data/test/test_helper.rb +25 -1
  48. metadata +18 -78
  49. data/bin/mirahp +0 -27
  50. data/bin/mirahp.cmd +0 -16
  51. data/examples/Fib.class +0 -0
  52. data/javalib/mirah-bootstrap.jar +0 -0
  53. data/javalib/mirah-builtins.jar +0 -0
  54. data/javalib/mirah-compiler.jar +0 -0
  55. data/javalib/mirah-mirrors.jar +0 -0
  56. data/javalib/mirah-newast-transitional.jar +0 -0
  57. data/javalib/mirah-parser.jar +0 -0
  58. data/javalib/mirah-util.jar +0 -0
  59. data/lib/mirah/ast.rb +0 -43
  60. data/lib/mirah/ast/scope.rb +0 -262
  61. data/lib/mirah/commands/base.rb +0 -59
  62. data/lib/mirah/commands/compile.rb +0 -39
  63. data/lib/mirah/commands/parse.rb +0 -36
  64. data/lib/mirah/commands/run.rb +0 -78
  65. data/lib/mirah/generator.rb +0 -150
  66. data/lib/mirah/jvm/compiler.rb +0 -50
  67. data/lib/mirah/jvm/compiler/base.rb +0 -421
  68. data/lib/mirah/jvm/compiler/jvm_bytecode.rb +0 -1194
  69. data/lib/mirah/jvm/method_lookup.rb +0 -307
  70. data/lib/mirah/jvm/types.rb +0 -45
  71. data/lib/mirah/jvm/types/array_type.rb +0 -60
  72. data/lib/mirah/jvm/types/ast_ext.rb +0 -31
  73. data/lib/mirah/jvm/types/basic_types.rb +0 -41
  74. data/lib/mirah/jvm/types/block_type.rb +0 -15
  75. data/lib/mirah/jvm/types/boolean.rb +0 -70
  76. data/lib/mirah/jvm/types/enumerable.rb +0 -80
  77. data/lib/mirah/jvm/types/extensions.rb +0 -110
  78. data/lib/mirah/jvm/types/factory.rb +0 -830
  79. data/lib/mirah/jvm/types/floats.rb +0 -99
  80. data/lib/mirah/jvm/types/generic_type.rb +0 -72
  81. data/lib/mirah/jvm/types/implicit_nil_type.rb +0 -29
  82. data/lib/mirah/jvm/types/integers.rb +0 -131
  83. data/lib/mirah/jvm/types/interface_definition.rb +0 -20
  84. data/lib/mirah/jvm/types/intrinsics.rb +0 -385
  85. data/lib/mirah/jvm/types/literals.rb +0 -89
  86. data/lib/mirah/jvm/types/meta_type.rb +0 -54
  87. data/lib/mirah/jvm/types/methods.rb +0 -946
  88. data/lib/mirah/jvm/types/null_type.rb +0 -39
  89. data/lib/mirah/jvm/types/number.rb +0 -184
  90. data/lib/mirah/jvm/types/primitive_type.rb +0 -76
  91. data/lib/mirah/jvm/types/source_mirror.rb +0 -274
  92. data/lib/mirah/jvm/types/type.rb +0 -311
  93. data/lib/mirah/jvm/types/type_definition.rb +0 -72
  94. data/lib/mirah/jvm/types/void_type.rb +0 -19
  95. data/lib/mirah/util/compilation_state.rb +0 -60
  96. data/test/core/commands_test.rb +0 -89
  97. data/test/core/generator_test.rb +0 -26
  98. data/test/fixtures/org/foo/LowerCaseInnerClass$inner.class +0 -0
  99. data/test/fixtures/org/foo/LowerCaseInnerClass.class +0 -0
  100. data/test/jvm/bytecode_test_helper.rb +0 -193
  101. data/test/jvm/factory_test.rb +0 -28
  102. data/test/jvm/java_typer_test.rb +0 -283
@@ -1,15 +0,0 @@
1
- module Mirah
2
- module JVM
3
- module Types
4
- class BlockType < Type
5
- def initialize
6
- super(':block', nil)
7
- end
8
-
9
- def isBlock
10
- true
11
- end
12
- end
13
- end
14
- end
15
- end
@@ -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'