mirah 0.0.12-java → 0.1.0-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 (171) hide show
  1. data/History.txt +372 -0
  2. data/README.txt +4 -5
  3. data/Rakefile +178 -55
  4. data/examples/appengine/Readme +3 -3
  5. data/examples/appengine/src/org/mirah/MirahApp.mirah +1 -1
  6. data/examples/appengine/src/org/mirah/list.dhtml +1 -1
  7. data/examples/bintrees.mirah +1 -1
  8. data/examples/edb.mirah +1 -1
  9. data/examples/fib.mirah +1 -1
  10. data/examples/interfaces.mirah +1 -1
  11. data/examples/macros/{string-each-char.mirah → string_each_char.mirah} +4 -5
  12. data/examples/maven/README.txt +1 -1
  13. data/examples/maven/src/main/mirah/hello_mirah.mirah +1 -1
  14. data/examples/plugins/appengine/Rakefile +1 -1
  15. data/examples/plugins/appengine/src/com/google/appengine/ext/duby/db/MetaModel.mirah +1 -1
  16. data/examples/plugins/appengine/src/com/google/appengine/ext/duby/db/Model.duby +1 -1
  17. data/examples/plugins/appengine/test/com/google/appengine/ext/duby/db/ModelTest.duby +1 -1
  18. data/examples/rosettacode/100-doors.mirah +6 -6
  19. data/examples/rosettacode/README.txt +3 -3
  20. data/examples/rosettacode/boolean-values.mirah +1 -1
  21. data/examples/rosettacode/comments.mirah +1 -1
  22. data/examples/rosettacode/count-occurrences-of-a-substring.mirah +1 -1
  23. data/examples/rosettacode/factorial.mirah +1 -1
  24. data/examples/rosettacode/fibonacci.mirah +1 -1
  25. data/examples/rosettacode/fizz-buzz.mirah +2 -2
  26. data/examples/rosettacode/flatten-a-list.mirah +4 -4
  27. data/examples/rosettacode/guess-the-number.mirah +2 -2
  28. data/examples/rosettacode/hamming-numbers.mirah +4 -4
  29. data/examples/rosettacode/is-string-numeric.mirah +22 -22
  30. data/examples/rosettacode/palindrome.mirah +2 -2
  31. data/examples/rosettacode/random-numbers.mirah +1 -1
  32. data/examples/rosettacode/repeat-a-string.mirah +1 -1
  33. data/examples/rosettacode/reverse-a-string.mirah +1 -1
  34. data/examples/rosettacode/rot-13.mirah +5 -5
  35. data/examples/rosettacode/secure-temporary-file.mirah +2 -2
  36. data/examples/rosettacode/sleep.mirah +1 -1
  37. data/examples/rosettacode/string-length.mirah +5 -5
  38. data/examples/swing.mirah +1 -1
  39. data/examples/test.edb +1 -1
  40. data/javalib/mirah-bootstrap.jar +0 -0
  41. data/javalib/mirah-builtins.jar +0 -0
  42. data/javalib/mirah-parser.jar +0 -0
  43. data/javalib/mirah-util.jar +0 -0
  44. data/lib/duby.rb +1 -1
  45. data/lib/mirah.rb +50 -28
  46. data/lib/mirah/ast.rb +15 -605
  47. data/lib/mirah/ast/scope.rb +98 -69
  48. data/lib/mirah/commands.rb +1 -1
  49. data/lib/mirah/commands/base.rb +7 -7
  50. data/lib/mirah/commands/compile.rb +3 -3
  51. data/lib/mirah/commands/parse.rb +7 -5
  52. data/lib/mirah/commands/run.rb +12 -19
  53. data/lib/mirah/compiler.rb +15 -23
  54. data/lib/mirah/errors.rb +16 -1
  55. data/lib/mirah/generator.rb +79 -39
  56. data/lib/mirah/jvm/compiler.rb +1 -19
  57. data/lib/mirah/jvm/compiler/base.rb +233 -90
  58. data/lib/mirah/jvm/compiler/jvm_bytecode.rb +675 -363
  59. data/lib/mirah/jvm/method_lookup.rb +134 -65
  60. data/lib/mirah/jvm/typer.rb +10 -5
  61. data/lib/mirah/jvm/types.rb +10 -2
  62. data/lib/mirah/jvm/types/array_type.rb +10 -12
  63. data/lib/mirah/{compiler/type.rb → jvm/types/ast_ext.rb} +12 -8
  64. data/lib/mirah/jvm/types/basic_types.rb +26 -33
  65. data/lib/mirah/jvm/types/bitescript_ext.rb +1 -1
  66. data/lib/mirah/jvm/types/block_type.rb +15 -0
  67. data/lib/mirah/jvm/types/boolean.rb +8 -4
  68. data/lib/mirah/jvm/types/dynamic_type.rb +12 -13
  69. data/lib/mirah/jvm/types/enumerable.rb +7 -7
  70. data/lib/mirah/jvm/types/extensions.rb +11 -6
  71. data/lib/mirah/jvm/types/factory.rb +624 -94
  72. data/lib/mirah/jvm/types/floats.rb +21 -15
  73. data/lib/mirah/jvm/types/generic_type.rb +72 -0
  74. data/lib/mirah/jvm/types/implicit_nil_type.rb +29 -0
  75. data/lib/mirah/jvm/types/integers.rb +26 -71
  76. data/lib/mirah/jvm/types/interface_definition.rb +3 -3
  77. data/lib/mirah/jvm/types/intrinsics.rb +203 -168
  78. data/lib/mirah/jvm/types/literals.rb +6 -6
  79. data/lib/mirah/jvm/types/meta_type.rb +13 -4
  80. data/lib/mirah/jvm/types/methods.rb +281 -93
  81. data/lib/mirah/jvm/types/null_type.rb +17 -5
  82. data/lib/mirah/jvm/types/number.rb +10 -7
  83. data/lib/mirah/jvm/types/primitive_type.rb +17 -6
  84. data/lib/mirah/jvm/types/source_mirror.rb +12 -7
  85. data/lib/mirah/jvm/types/type.rb +107 -23
  86. data/lib/mirah/jvm/types/type_definition.rb +25 -10
  87. data/lib/mirah/jvm/types/unreachable_type.rb +1 -1
  88. data/lib/mirah/jvm/types/void_type.rb +3 -3
  89. data/lib/mirah/parser.rb +154 -16
  90. data/lib/mirah/plugin/edb.rb +1 -1
  91. data/lib/mirah/transform.rb +1 -2
  92. data/lib/mirah/transform/ast_ext.rb +24 -43
  93. data/lib/mirah/transform/transformer.rb +29 -224
  94. data/lib/mirah/typer.rb +2 -16
  95. data/lib/mirah/util/argument_processor.rb +25 -10
  96. data/lib/mirah/util/class_loader.rb +1 -1
  97. data/lib/mirah/util/compilation_state.rb +16 -17
  98. data/lib/mirah/util/delegate.rb +2 -2
  99. data/lib/mirah/util/logging.rb +110 -0
  100. data/lib/mirah/util/process_errors.rb +69 -11
  101. data/lib/mirah/version.rb +1 -1
  102. data/test/core/commands_test.rb +6 -24
  103. data/test/core/env_test.rb +5 -5
  104. data/{lib/mirah/jvm/source_generator/typer.rb → test/core/generator_test.rb} +9 -9
  105. data/test/core/typer_test.rb +196 -158
  106. data/test/core/util/argument_processor_test.rb +10 -10
  107. data/test/core/util/class_loader_test.rb +6 -5
  108. data/test/fixtures/org/foo/LowerCaseInnerClass$inner.class +0 -0
  109. data/test/fixtures/org/foo/LowerCaseInnerClass.class +0 -0
  110. data/test/fixtures/org/foo/LowerCaseInnerClass.java +7 -0
  111. data/test/jvm/annotations_test.rb +5 -5
  112. data/test/jvm/blocks_test.rb +140 -88
  113. data/test/jvm/bytecode_test_helper.rb +112 -94
  114. data/test/jvm/cast_test.rb +162 -0
  115. data/test/jvm/constructors_test.rb +18 -8
  116. data/test/jvm/enumerable_test.rb +77 -44
  117. data/test/jvm/example_test.rb +53 -0
  118. data/test/jvm/factory_test.rb +7 -1
  119. data/test/jvm/generics_test.rb +57 -0
  120. data/test/jvm/hash_test.rb +106 -0
  121. data/test/jvm/import_test.rb +81 -0
  122. data/test/jvm/interface_test.rb +73 -0
  123. data/test/jvm/java_typer_test.rb +92 -66
  124. data/{lib/mirah/typer/base.rb → test/jvm/jvm_commands_test.rb} +6 -10
  125. data/test/jvm/jvm_compiler_test.rb +170 -604
  126. data/test/jvm/list_extensions_test.rb +23 -0
  127. data/test/jvm/macros_test.rb +197 -32
  128. data/test/jvm/main_method_test.rb +4 -4
  129. data/test/jvm/numeric_extensions_test.rb +13 -0
  130. data/test/jvm/rescue_test.rb +73 -16
  131. data/test/jvm/varargs_test.rb +65 -0
  132. data/test/test_helper.rb +1 -2
  133. metadata +234 -251
  134. data/examples/SortClosure$__xform_tmp_1.class +0 -0
  135. data/examples/SortClosure$__xform_tmp_2.class +0 -0
  136. data/examples/SortClosure.class +0 -0
  137. data/examples/macros/StringEachChar$Extension1.class +0 -0
  138. data/lib/mirah/ast/call.rb +0 -345
  139. data/lib/mirah/ast/class.rb +0 -359
  140. data/lib/mirah/ast/flow.rb +0 -381
  141. data/lib/mirah/ast/intrinsics.rb +0 -563
  142. data/lib/mirah/ast/literal.rb +0 -178
  143. data/lib/mirah/ast/local.rb +0 -112
  144. data/lib/mirah/ast/method.rb +0 -408
  145. data/lib/mirah/ast/structure.rb +0 -387
  146. data/lib/mirah/ast/type.rb +0 -146
  147. data/lib/mirah/commands/base.rb~ +0 -57
  148. data/lib/mirah/compiler/call.rb +0 -45
  149. data/lib/mirah/compiler/class.rb +0 -81
  150. data/lib/mirah/compiler/flow.rb +0 -109
  151. data/lib/mirah/compiler/literal.rb +0 -130
  152. data/lib/mirah/compiler/local.rb +0 -59
  153. data/lib/mirah/compiler/method.rb +0 -44
  154. data/lib/mirah/compiler/structure.rb +0 -65
  155. data/lib/mirah/jvm/compiler/java_source.rb +0 -787
  156. data/lib/mirah/jvm/method_lookup.rb~ +0 -247
  157. data/lib/mirah/jvm/source_generator/builder.rb +0 -468
  158. data/lib/mirah/jvm/source_generator/loops.rb +0 -131
  159. data/lib/mirah/jvm/source_generator/precompile.rb +0 -210
  160. data/lib/mirah/plugin/gwt.rb +0 -189
  161. data/lib/mirah/plugin/java.rb +0 -70
  162. data/lib/mirah/transform/error.rb +0 -13
  163. data/lib/mirah/transform/helper.rb +0 -765
  164. data/lib/mirah/typer/simple.rb +0 -384
  165. data/lib/mirah/version.rb~ +0 -18
  166. data/test/core/ast_test.rb +0 -382
  167. data/test/core/compilation_test.rb +0 -130
  168. data/test/core/macros_test.rb +0 -61
  169. data/test/jvm/javac_test_helper.rb +0 -89
  170. data/test/jvm/jvm_compiler_test.rb~ +0 -2181
  171. data/test/plugins/gwt_test.rb +0 -69
@@ -24,7 +24,7 @@ module Mirah::JVM::Types
24
24
  super(default_type)
25
25
  @narrowed = default_type != narrowed_type && narrowed_type
26
26
  end
27
-
27
+
28
28
  def hash
29
29
  __getobj__.hash
30
30
  end
@@ -38,12 +38,12 @@ module Mirah::JVM::Types
38
38
  end
39
39
  end
40
40
  end
41
-
41
+
42
42
  class FixnumLiteral < NarrowingType
43
43
  def self.range(type)
44
44
  type::MIN_VALUE .. type::MAX_VALUE
45
45
  end
46
-
46
+
47
47
  BYTE_RANGE = range(java.lang.Byte)
48
48
  SHORT_RANGE = range(java.lang.Short)
49
49
  INT_RANGE = range(java.lang.Integer)
@@ -56,7 +56,7 @@ module Mirah::JVM::Types
56
56
  else
57
57
  Long
58
58
  end
59
-
59
+
60
60
  # TODO chars?
61
61
  # There's not really any way to tell if we should narrow to a char
62
62
  # or a byte/short. I suppose we could try both, but that seems ugly.
@@ -71,7 +71,7 @@ module Mirah::JVM::Types
71
71
  else
72
72
  Long
73
73
  end
74
-
74
+
75
75
  super(default_type, narrowed_type)
76
76
  end
77
77
  end
@@ -86,4 +86,4 @@ module Mirah::JVM::Types
86
86
  super(Double, Double)
87
87
  end
88
88
  end
89
- end
89
+ end
@@ -5,7 +5,7 @@ module Mirah
5
5
  attr_reader :unmeta
6
6
 
7
7
  def initialize(unmeta)
8
- @name = unmeta.name
8
+ super(unmeta.type_system, unmeta.name)
9
9
  @unmeta = unmeta
10
10
  end
11
11
 
@@ -13,6 +13,11 @@ module Mirah
13
13
  @unmeta.basic_type
14
14
  end
15
15
 
16
+ def name
17
+ return @unmeta.name if @unmeta
18
+ super
19
+ end
20
+
16
21
  def meta?
17
22
  true
18
23
  end
@@ -22,10 +27,14 @@ module Mirah
22
27
  end
23
28
 
24
29
  def superclass
25
- @unmeta.superclass.meta if @unmeta.superclass
30
+ if @unmeta.superclass
31
+ @unmeta.superclass.meta
32
+ else
33
+ nil
34
+ end
26
35
  end
27
36
 
28
- def interfaces
37
+ def interfaces(include_parent=true)
29
38
  []
30
39
  end
31
40
 
@@ -42,4 +51,4 @@ module Mirah
42
51
  end
43
52
  end
44
53
  end
45
- end
54
+ end
@@ -31,14 +31,36 @@ module Mirah::JVM::Types
31
31
  module ArgumentConversion
32
32
  def convert_args(compiler, values, types=nil)
33
33
  # TODO boxing/unboxing
34
- # TODO varargs
35
34
  types ||= argument_types
36
- values.zip(types).each do |value, type|
37
- compiler.compile(value, true)
38
- if type.primitive? && type != value.inferred_type
39
- value.inferred_type.widen(compiler.method, type)
35
+ needs_to_build_varargs_array = false
36
+
37
+ if respond_to?(:varargs?) && varargs?
38
+ non_varargs_types = types[0..-2]
39
+ non_varargs_values = values.first non_varargs_types.size
40
+
41
+ varargs_values = values.to_a.last(values.size - non_varargs_values.size)
42
+ varargs_type = types.last
43
+
44
+ unless varargs_values.length == 1 &&
45
+ varargs_type.compatible?(compiler.inferred_type(varargs_values.first))
46
+ needs_to_build_varargs_array = true
47
+ values = non_varargs_values
40
48
  end
41
49
  end
50
+
51
+ values_and_types = values.zip(types)
52
+
53
+ values_and_types.each do |value, type|
54
+ compiler.visit(value, true)
55
+ in_type = compiler.inferred_type(value)
56
+ if in_type.primitive? && type != in_type
57
+ in_type.compile_widen(compiler.method, type)
58
+ end
59
+ end
60
+
61
+ if needs_to_build_varargs_array
62
+ compiler.visitVarargsArray(varargs_type, varargs_values)
63
+ end
42
64
  end
43
65
  end
44
66
 
@@ -57,8 +79,8 @@ module Mirah::JVM::Types
57
79
  @block = block
58
80
  end
59
81
 
60
- def call(builder, ast, expression)
61
- @block.call(builder, ast, expression)
82
+ def call(builder, ast, expression, *args)
83
+ @block.call(builder, ast, expression, *args)
62
84
  end
63
85
 
64
86
  def declaring_class
@@ -80,14 +102,41 @@ module Mirah::JVM::Types
80
102
  def exceptions
81
103
  []
82
104
  end
105
+
106
+ def varargs?
107
+ false
108
+ end
109
+ end
110
+
111
+ class Macro
112
+ java_import 'org.mirah.typer.InlineCode'
113
+ java_import 'org.mirah.typer.NodeBuilder'
114
+ attr_reader :name, :argument_types, :return_type
115
+
116
+ def initialize(klass, name, args, &block)
117
+ raise ArgumentError, "Block required" unless block_given?
118
+ @class = klass
119
+ @name = name
120
+ @argument_types = args
121
+ raise ArgumentError unless args.all?
122
+ @return_type = InlineCode.new(block.to_java(NodeBuilder))
123
+ end
124
+
125
+ def declaring_class
126
+ @class
127
+ end
83
128
  end
84
129
 
85
130
  class JavaCallable
86
131
  include ArgumentConversion
132
+ java_import 'org.mirah.typer.ResolvedType'
133
+ java_import 'org.mirah.typer.TypeSystem'
87
134
 
88
135
  attr_accessor :member
89
136
 
90
- def initialize(member)
137
+ def initialize(types, member)
138
+ raise ArgumentError unless types.kind_of?(TypeSystem)
139
+ @types = types
91
140
  @member = member
92
141
  end
93
142
 
@@ -107,10 +156,10 @@ module Mirah::JVM::Types
107
156
  class JavaConstructor < JavaCallable
108
157
  def argument_types
109
158
  @argument_types ||= @member.argument_types.map do |arg|
110
- if arg.kind_of?(AST::TypeReference) || arg.nil?
159
+ if arg.kind_of?(Type) || arg.nil?
111
160
  arg
112
161
  else
113
- AST.type(nil, arg)
162
+ @types.type(nil, arg)
114
163
  end
115
164
  end
116
165
  end
@@ -121,23 +170,30 @@ module Mirah::JVM::Types
121
170
 
122
171
  def exceptions
123
172
  @member.exception_types.map do |exception|
124
- if exception.kind_of?(Mirah::JVM::Types::Type)
173
+ if exception.kind_of?(ResolvedType)
125
174
  exception
126
175
  else
127
- Mirah::AST.type(nil, exception.class_name)
176
+ @types.type(nil, exception.class_name)
128
177
  end
129
178
  end
130
179
  end
131
180
 
132
181
  def declaring_class
133
- AST.type(nil, @member.declaring_class)
182
+ @types.type(nil, @member.declaring_class)
183
+ end
184
+
185
+ def type_parameters
186
+ @declaring_class and @declaring_class.jvm_type.type_parameters
134
187
  end
135
188
 
136
- def call(compiler, ast, expression)
137
- target = ast.target.inferred_type
138
- compiler.method.new target
139
- compiler.method.dup if expression
140
- convert_args(compiler, ast.parameters)
189
+ def call(compiler, ast, expression, parameters=nil, delegate=false)
190
+ target = compiler.inferred_type(ast.target)
191
+ unless delegate
192
+ compiler.method.new target
193
+ compiler.method.dup if expression
194
+ end
195
+ parameters ||= ast.parameters
196
+ convert_args(compiler, parameters)
141
197
  compiler.method.invokespecial(
142
198
  target,
143
199
  "<init>",
@@ -147,15 +203,20 @@ module Mirah::JVM::Types
147
203
  def constructor?
148
204
  true
149
205
  end
206
+
207
+ def varargs?
208
+ @member.varargs?
209
+ end
210
+
150
211
  end
151
212
 
152
213
  class JavaMethod < JavaConstructor
153
214
  def return_type
154
215
  @return_type ||= begin
155
216
  if void?
156
- Void
217
+ @types.type(nil, 'void')
157
218
  else
158
- AST.type(nil, @member.return_type)
219
+ @types.type(nil, @member.return_type)
159
220
  end
160
221
  end
161
222
  end
@@ -168,6 +229,10 @@ module Mirah::JVM::Types
168
229
  @member.abstract?
169
230
  end
170
231
 
232
+ def type_parameters
233
+ @member.type_parameters
234
+ end
235
+
171
236
  def void?
172
237
  return_type = @member.return_type
173
238
  return true if return_type.nil?
@@ -181,9 +246,9 @@ module Mirah::JVM::Types
181
246
  false
182
247
  end
183
248
 
184
- def call(compiler, ast, expression)
185
- target = ast.target.inferred_type
186
- ast.target.compile(compiler, true)
249
+ def call(compiler, ast, expression, parameters=nil)
250
+ target = compiler.inferred_type(ast.target)
251
+ compiler.visit(ast.target, true)
187
252
 
188
253
  # if expression, void methods return the called object,
189
254
  # for consistency and chaining
@@ -193,7 +258,8 @@ module Mirah::JVM::Types
193
258
  compiler.method.dup
194
259
  end
195
260
 
196
- convert_args(compiler, ast.parameters)
261
+ parameters ||= ast.parameters
262
+ convert_args(compiler, parameters)
197
263
  if target.interface?
198
264
  compiler.method.invokeinterface(
199
265
  target,
@@ -206,14 +272,22 @@ module Mirah::JVM::Types
206
272
  [@member.return_type, *@member.argument_types])
207
273
  end
208
274
 
275
+ if expression && !void?
276
+ # Insert a cast if the inferred type and actual type differ. This is part of generics support.
277
+ inferred_return_type = compiler.inferred_type(ast)
278
+ if !inferred_return_type.assignableFrom(return_type)
279
+ compiler.method.checkcast(inferred_return_type)
280
+ end
281
+ end
282
+
209
283
  unless expression || void?
210
284
  return_type.pop(compiler.method)
211
285
  end
212
286
  end
213
287
 
214
- def call_special(compiler, ast, expression)
215
- target = ast.target.inferred_type
216
- ast.target.compile(compiler, true)
288
+ def call_special(compiler, target, target_type, parameters, expression)
289
+ target_type ||= compiler.inferred_type(target)
290
+ compiler.visit(target, true)
217
291
 
218
292
  # if expression, void methods return the called object,
219
293
  # for consistency and chaining
@@ -223,12 +297,12 @@ module Mirah::JVM::Types
223
297
  compiler.method.dup
224
298
  end
225
299
 
226
- convert_args(compiler, ast.parameters)
227
- if target.interface?
300
+ convert_args(compiler, parameters)
301
+ if target_type.interface?
228
302
  raise "interfaces should not receive call_special"
229
303
  else
230
304
  compiler.method.invokespecial(
231
- target,
305
+ target_type,
232
306
  name,
233
307
  [@member.return_type, *@member.argument_types])
234
308
  end
@@ -240,9 +314,10 @@ module Mirah::JVM::Types
240
314
  end
241
315
 
242
316
  class JavaStaticMethod < JavaMethod
243
- def call(compiler, ast, expression)
317
+ def call(compiler, ast, expression, parameters=nil)
244
318
  target = declaring_class
245
- convert_args(compiler, ast.parameters)
319
+ parameters ||= ast.parameters
320
+ convert_args(compiler, parameters)
246
321
  compiler.method.invokestatic(
247
322
  target,
248
323
  name,
@@ -256,13 +331,14 @@ module Mirah::JVM::Types
256
331
  end
257
332
 
258
333
  class JavaDynamicMethod < JavaMethod
259
- def initialize(name, *types)
334
+ def initialize(type_system, name, *argument_types)
335
+ super(type_system, nil)
260
336
  @name = name
261
- @types = types
337
+ @argument_types = argument_types
262
338
  end
263
339
 
264
340
  def return_type
265
- AST.type(nil, 'dynamic')
341
+ @types.type(nil, 'dynamic')
266
342
  end
267
343
 
268
344
  def declaring_class
@@ -270,17 +346,21 @@ module Mirah::JVM::Types
270
346
  end
271
347
 
272
348
  def argument_types
273
- @types
349
+ @argument_types
274
350
  end
275
351
 
276
- def call(compiler, ast, expression)
277
- target = ast.target.inferred_type
278
- ast.target.compile(compiler, true)
352
+ def call(compiler, ast, expression, parameters=nil)
353
+ unless compiler.respond_to?(:supports_invokedynamic?) && compiler.supports_invokedynamic?
354
+ raise Mirah::MirahError, "Target JVM version: #{compiler.target_jvm_version} doesn't support invoke dynamic"
355
+ end
356
+ target = compiler.inferred_type(ast.target)
357
+ compiler.visit(ast.target, true)
279
358
 
280
- ast.parameters.each do |param|
281
- param.compile(compiler, true)
359
+ parameters ||= ast.parameters
360
+ parameters.each do |param|
361
+ compiler.visit(param, true)
282
362
  end
283
- handle = compiler.method.mh_invokestatic(
363
+ handle = compiler.method.h_invokestatic(
284
364
  org.dynalang.dynalink.DefaultBootstrapper,
285
365
  "bootstrap",
286
366
  java.lang.invoke.CallSite,
@@ -289,7 +369,7 @@ module Mirah::JVM::Types
289
369
  java.lang.invoke.MethodType)
290
370
  compiler.method.invokedynamic(
291
371
  "dyn:callPropWithThis:#{name}",
292
- [return_type, target, *@types],
372
+ [return_type, target, *@argument_types],
293
373
  handle)
294
374
 
295
375
  unless expression
@@ -304,7 +384,7 @@ module Mirah::JVM::Types
304
384
  end
305
385
 
306
386
  def return_type
307
- AST.type(nil, @member.type)
387
+ @types.type(nil, @member.type)
308
388
  end
309
389
 
310
390
  def public?
@@ -321,8 +401,8 @@ module Mirah::JVM::Types
321
401
  []
322
402
  end
323
403
 
324
- def call(compiler, ast, expression)
325
- target = ast.target.inferred_type
404
+ def call(compiler, ast, expression, parameters=nil)
405
+ target = compiler.inferred_type(ast.target)
326
406
 
327
407
  # TODO: assert that no args are being passed, though that should have failed lookup
328
408
 
@@ -330,7 +410,7 @@ module Mirah::JVM::Types
330
410
  if @member.static?
331
411
  compiler.method.getstatic(target, name, @member.type)
332
412
  else
333
- ast.target.compile(compiler, true)
413
+ compiler.visit(ast.target, true)
334
414
  compiler.method.getfield(target, name, @member.type)
335
415
  end
336
416
  end
@@ -339,25 +419,26 @@ module Mirah::JVM::Types
339
419
 
340
420
  class JavaFieldSetter < JavaFieldAccessor
341
421
  def return_type
342
- AST.type(nil, @member.type)
422
+ @types.type(nil, @member.type)
343
423
  end
344
424
 
345
425
  def argument_types
346
- [AST.type(nil, @member.type)]
426
+ [@types.type(nil, @member.type)]
347
427
  end
348
428
 
349
- def call(compiler, ast, expression)
350
- target = ast.target.inferred_type
429
+ def call(compiler, ast, expression, parameters=nil)
430
+ target = compiler.inferred_type(ast.target)
351
431
 
352
432
  # TODO: assert that no args are being passed, though that should have failed lookup
353
433
 
434
+ parameters ||= ast.parameters
354
435
  if @member.static?
355
- convert_args(compiler, ast.parameters)
436
+ convert_args(compiler, parameters)
356
437
  compiler.method.dup if expression
357
438
  compiler.method.putstatic(target, name, @member.type)
358
439
  else
359
- ast.target.compile(compiler, true)
360
- convert_args(compiler, ast.parameters)
440
+ compiler.visit(ast.target, true)
441
+ convert_args(compiler, parameters)
361
442
  compiler.method.dup_x2 if expression
362
443
  compiler.method.putfield(target, name, @member.type)
363
444
  end
@@ -369,7 +450,7 @@ module Mirah::JVM::Types
369
450
  attr_reader :exception_types
370
451
 
371
452
  def initialize(klass, name, args, return_type, static, exceptions)
372
- if return_type == Void
453
+ if return_type.name == 'void' || return_type.name == ':unreachable'
373
454
  return_type = nil
374
455
  end
375
456
  @declaring_class = klass
@@ -387,11 +468,111 @@ module Mirah::JVM::Types
387
468
  def abstract?
388
469
  @declaring_class.interface?
389
470
  end
471
+
472
+ def varargs?
473
+ false
474
+ end
390
475
  end
391
476
 
392
477
  class Type
478
+ def method_listeners
479
+ if meta?
480
+ unmeta.method_listeners
481
+ else
482
+ @method_listeners ||= {}
483
+ end
484
+ end
485
+
486
+ def method_updated(name)
487
+ listeners = method_listeners[name]
488
+ listeners.values.each do |l|
489
+ if l.kind_of?(Proc)
490
+ l.call(name)
491
+ else
492
+ l.method_updated(name)
493
+ end
494
+ end if listeners
495
+ end
496
+
497
+ def add_method_listener(name, listener=nil, &block)
498
+ listeners = method_listeners[name] ||= {}
499
+ if listener
500
+ unless listener.respond_to?(:method_updated) || listener.kind_of?(Proc)
501
+ raise "Invalid listener"
502
+ end
503
+ listeners[listener] = listener
504
+ else
505
+ listeners[block] = block
506
+ end
507
+ if !self.meta? && jvm_type && superclass && !superclass.isError
508
+ superclass.add_method_listener(name, self)
509
+ end
510
+ interfaces.each {|i| i.add_method_listener(name, self) unless i.isError}
511
+ end
512
+
513
+ # TODO take a scope and check visibility
514
+ def find_callable_macros(name)
515
+ interfaces = []
516
+ macros = find_callable_macros2(name, interfaces)
517
+ seen = {}
518
+ until interfaces.empty?
519
+ interface = interfaces.pop
520
+ next if seen[interface] || interface.isError
521
+ seen[interface] = true
522
+ interfaces.concat(interface.interfaces)
523
+ macros.concat(interface.declared_macros(name))
524
+ end
525
+ macros
526
+ end
527
+
528
+ def find_callable_macros2(name, interfaces)
529
+ macros = []
530
+ interfaces.concat(self.interfaces)
531
+ macros.concat(declared_macros(name))
532
+ if superclass && !superclass.error?
533
+ macros.concat(superclass.find_callable_macros2(name, interfaces))
534
+ end
535
+ macros
536
+ end
537
+
538
+ # TODO take a scope and check visibility
539
+ def find_callable_methods(name, include_interfaces=false, &proc)
540
+ if block_given?
541
+ add_method_listener(name) {proc.call(find_callable_methods(name))}
542
+ proc.call(find_callable_methods(name))
543
+ return
544
+ end
545
+ interfaces = if self.interface? || include_interfaces # TODO || self.abstract?
546
+ []
547
+ else
548
+ nil
549
+ end
550
+ methods = find_callable_methods2(name, interfaces)
551
+ if interfaces
552
+ seen = {}
553
+ until interfaces.empty?
554
+ interface = interfaces.pop
555
+ next if seen[interface]
556
+ seen[interface] = true
557
+ interfaces.concat(interface.interfaces)
558
+ methods.concat(interface.declared_instance_methods(name))
559
+ end
560
+ end
561
+ methods
562
+ end
563
+
564
+ def find_callable_methods2(name, interfaces)
565
+ methods = []
566
+ interfaces.concat(self.interfaces) if interfaces
567
+ methods.concat(declared_instance_methods(name))
568
+ if superclass && !superclass.error?
569
+ methods.concat(superclass.find_callable_methods2(name, interfaces))
570
+ end
571
+ methods
572
+ end
573
+
393
574
  def get_method(name, args)
394
- method = find_method(self, name, args, meta?)
575
+ method = find_method(self, name, args, nil, meta?)
395
576
  unless method
396
577
  # Allow constant narrowing for assignment methods
397
578
  if name =~ /=$/ && args[-1].respond_to?(:narrow!)
@@ -407,9 +588,9 @@ module Mirah::JVM::Types
407
588
  begin
408
589
  descriptors = types.map {|type| BiteScript::Signature.class_id(type)}
409
590
  constructor = jvm_type.getConstructor(*descriptors)
410
- return JavaConstructor.new(constructor) if constructor
591
+ return JavaConstructor.new(@type_system, constructor) if constructor
411
592
  rescue => ex
412
- log(ex.message)
593
+ log("#{ex.message}\n#{ex.backtrace.join("\n")}")
413
594
  end
414
595
  raise NameError, "No constructor #{name}(#{types.join ', '})"
415
596
  end
@@ -419,7 +600,7 @@ module Mirah::JVM::Types
419
600
  return intrinsic if intrinsic
420
601
  jvm_types = types.map {|type| type.jvm_type}
421
602
 
422
- return JavaDynamicMethod.new(name, *jvm_types) if dynamic?
603
+ return JavaDynamicMethod.new(@type_system, name, *jvm_types) if dynamic?
423
604
 
424
605
  begin
425
606
  descriptors = types.map {|type| BiteScript::Signature.class_id(type)}
@@ -429,7 +610,7 @@ module Mirah::JVM::Types
429
610
  method = superclass.java_method(name, *types) rescue nil
430
611
  end
431
612
 
432
- if method.nil? && jvm_type.abstract?
613
+ if method.nil? && jvm_type && jvm_type.abstract?
433
614
  interfaces.each do |interface|
434
615
  method = interface.java_method(name, *types) rescue nil
435
616
  break if method
@@ -438,11 +619,11 @@ module Mirah::JVM::Types
438
619
 
439
620
  return method if method.kind_of?(JavaCallable)
440
621
  if method && method.static? == meta?
441
- return JavaStaticMethod.new(method) if method.static?
442
- return JavaMethod.new(method)
622
+ return JavaStaticMethod.new(@type_system, method) if method.static?
623
+ return JavaMethod.new(@type_system, method)
443
624
  end
444
625
  rescue => ex
445
- log(ex.message)
626
+ log("#{ex.message}\n#{ex.backtrace.join("\n")}")
446
627
  end
447
628
  raise NameError, "No method #{self.name}.#{name}(#{types.join ', '})"
448
629
  end
@@ -451,7 +632,7 @@ module Mirah::JVM::Types
451
632
  methods = []
452
633
  if jvm_type && !array?
453
634
  jvm_type.getDeclaredMethods(name).each do |method|
454
- methods << JavaMethod.new(method) unless method.static?
635
+ methods << JavaMethod.new(@type_system, method) unless method.static?
455
636
  end
456
637
  end
457
638
  methods.concat((meta? ? unmeta : self).declared_intrinsics(name))
@@ -461,7 +642,7 @@ module Mirah::JVM::Types
461
642
  methods = []
462
643
  if jvm_type && !unmeta.array?
463
644
  jvm_type.getDeclaredMethods(name).each do |method|
464
- methods << JavaStaticMethod.new(method) if method.static?
645
+ methods << JavaStaticMethod.new(@type_system, method) if method.static?
465
646
  end
466
647
  end
467
648
  methods.concat(meta.declared_intrinsics(name))
@@ -469,14 +650,14 @@ module Mirah::JVM::Types
469
650
 
470
651
  def declared_constructors
471
652
  jvm_type.getConstructors.map do |method|
472
- JavaConstructor.new(method)
653
+ JavaConstructor.new(@type_system, method)
473
654
  end
474
655
  end
475
656
 
476
657
  def field_getter(name)
477
658
  if jvm_type
478
659
  field = jvm_type.getField(name)
479
- JavaFieldGetter.new(field) if field
660
+ JavaFieldGetter.new(@type_system, field) if field
480
661
  else
481
662
  nil
482
663
  end
@@ -485,7 +666,7 @@ module Mirah::JVM::Types
485
666
  def field_setter(name)
486
667
  if jvm_type
487
668
  field = jvm_type.getField(name)
488
- JavaFieldSetter.new(field) if field
669
+ JavaFieldSetter.new(@type_system, field) if field
489
670
  else
490
671
  nil
491
672
  end
@@ -493,13 +674,14 @@ module Mirah::JVM::Types
493
674
 
494
675
  def inner_class_getter(name)
495
676
  full_name = "#{self.name}$#{name}"
496
- inner_class = Mirah::AST.type(nil, full_name) rescue nil
677
+ inner_class = @type_system.type(nil, full_name) rescue nil
497
678
  return unless inner_class
679
+
498
680
  inner_class.inner_class = true
499
- add_macro(name) do |transformer, call|
500
- Mirah::AST::Constant.new(call.parent, call.position, full_name)
681
+ macro = Macro.new(self, name, []) do |call, typer|
682
+ Mirah::AST::Constant.new(call.position, Mirah::AST::SimpleString.new(call.position, full_name))
501
683
  end
502
- intrinsics[name][[]]
684
+ intrinsics[name][[]] = macro
503
685
  end
504
686
  end
505
687
 
@@ -547,17 +729,12 @@ module Mirah::JVM::Types
547
729
  end
548
730
 
549
731
  def constructors
550
- @constructors ||= []
551
- end
552
-
553
- def default_constructor
554
- if constructors.empty?
732
+ if @constructors.nil?
733
+ @constructors = []
555
734
  declare_method('initialize', [], self, [])
556
- @default_constructor_added = true
557
- constructors[0]
558
- else
559
- constructor
735
+ @have_default_constructor = true
560
736
  end
737
+ @constructors
561
738
  end
562
739
 
563
740
  def instance_methods
@@ -570,25 +747,36 @@ module Mirah::JVM::Types
570
747
 
571
748
  def declare_method(name, arguments, type, exceptions)
572
749
  raise "Bad args" unless arguments.all?
750
+ if type.isError
751
+ instance_methods.delete(name)
752
+ method_updated(name)
753
+ return
754
+ end
573
755
  member = MirahMember.new(self, name, arguments, type, false, exceptions)
574
756
  if name == 'initialize'
575
- if @default_constructor_added
576
- if arguments.empty?
577
- @default_constructor_added = false
578
- else
579
- raise "Can't add constructor #{member} after using the default."
580
- end
581
- else
582
- constructors << JavaConstructor.new(member)
757
+ # The ordering is important here:
758
+ # The first call to constructors initializes @have_default_constructor.
759
+ if constructors.size == 1 && @have_default_constructor
760
+ constructors.clear
761
+ @have_default_constructor = false
762
+ elsif constructors.size > 1 && @have_default_constructor
763
+ raise "Invalid state: default constructor but #{constructors.size} constructors"
583
764
  end
765
+ constructors << JavaConstructor.new(@type_system, member)
584
766
  else
585
- instance_methods[name] << JavaMethod.new(member)
767
+ instance_methods[name] << JavaMethod.new(@type_system, member)
586
768
  end
769
+ method_updated(name)
587
770
  end
588
771
 
589
772
  def declare_static_method(name, arguments, type, exceptions)
590
- member = MirahMember.new(self, name, arguments, type, true, exceptions)
591
- static_methods[name] << JavaStaticMethod.new(member)
773
+ if type.isError
774
+ static_methods.delete(name)
775
+ else
776
+ member = MirahMember.new(self, name, arguments, type, true, exceptions)
777
+ static_methods[name] << JavaStaticMethod.new(@type_system, member)
778
+ end
779
+ method_updated(name)
592
780
  end
593
781
 
594
782
  def interface?
@@ -629,4 +817,4 @@ module Mirah::JVM::Types
629
817
  nil
630
818
  end
631
819
  end
632
- end
820
+ end