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