mirah 0.1.0.pre-java → 0.1.1-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. data/History.txt +736 -0
  2. data/README.md +71 -0
  3. data/Rakefile +227 -73
  4. data/examples/Fib.class +0 -0
  5. data/examples/macros/{string-each-char.mirah → string_each_char.mirah} +2 -3
  6. data/examples/simple_class.mirah +3 -3
  7. data/examples/{dynamic.mirah → simple_class.mirah~} +7 -12
  8. data/javalib/mirah-bootstrap.jar +0 -0
  9. data/javalib/mirah-builtins.jar +0 -0
  10. data/javalib/mirah-compiler.jar +0 -0
  11. data/javalib/mirah-parser.jar +0 -0
  12. data/javalib/mirah-util.jar +0 -0
  13. data/lib/mirah.rb +8 -1
  14. data/lib/mirah/ast.rb +1 -1
  15. data/lib/mirah/ast/scope.rb +16 -0
  16. data/lib/mirah/commands/base.rb +1 -3
  17. data/lib/mirah/compiler.rb +17 -3
  18. data/lib/mirah/errors.rb +10 -10
  19. data/lib/mirah/generator.rb +21 -9
  20. data/lib/mirah/jvm/compiler.rb +17 -0
  21. data/lib/mirah/jvm/compiler/base.rb +24 -5
  22. data/lib/mirah/jvm/compiler/jvm_bytecode.rb +83 -20
  23. data/lib/mirah/jvm/method_lookup.rb +43 -22
  24. data/lib/mirah/jvm/types.rb +1 -2
  25. data/lib/mirah/jvm/types/array_type.rb +1 -6
  26. data/lib/mirah/jvm/types/ast_ext.rb +31 -0
  27. data/lib/mirah/jvm/types/basic_types.rb +1 -2
  28. data/lib/mirah/jvm/types/boolean.rb +11 -10
  29. data/lib/mirah/jvm/types/extensions.rb +14 -5
  30. data/lib/mirah/jvm/types/factory.rb +128 -43
  31. data/lib/mirah/jvm/types/floats.rb +8 -10
  32. data/lib/mirah/jvm/types/integers.rb +16 -9
  33. data/lib/mirah/jvm/types/intrinsics.rb +17 -69
  34. data/lib/mirah/jvm/types/meta_type.rb +5 -0
  35. data/lib/mirah/jvm/types/methods.rb +317 -151
  36. data/lib/mirah/jvm/types/methods.rb~ +973 -0
  37. data/lib/mirah/jvm/types/number.rb +29 -6
  38. data/lib/mirah/jvm/types/primitive_type.rb +35 -7
  39. data/lib/mirah/jvm/types/source_mirror.rb +11 -6
  40. data/lib/mirah/jvm/types/type.rb +52 -0
  41. data/lib/mirah/jvm/types/type_definition.rb +8 -2
  42. data/lib/mirah/transform/ast_ext.rb +9 -31
  43. data/lib/mirah/transform/transformer.rb +1 -1
  44. data/lib/mirah/typer.rb +2 -1
  45. data/lib/mirah/util/argument_processor.rb +10 -14
  46. data/lib/mirah/util/argument_processor.rb~ +146 -0
  47. data/lib/mirah/util/compilation_state.rb +15 -9
  48. data/lib/mirah/util/process_errors.rb +8 -2
  49. data/lib/mirah/version.rb +2 -2
  50. data/lib/mirah_task.rb +0 -7
  51. data/test/core/typer_test.rb +21 -13
  52. data/test/core/util/argument_processor_test.rb +19 -19
  53. data/test/core/util/class_loader_test.rb +19 -4
  54. data/test/core/util/compilation_state_test.rb +38 -0
  55. data/test/fixtures/org/foo/LowerCaseInnerClass$inner.class +0 -0
  56. data/test/fixtures/org/foo/LowerCaseInnerClass.class +0 -0
  57. data/test/fixtures/org/foo/LowerCaseInnerClass.java +7 -0
  58. data/test/jvm/blocks_test.rb +50 -29
  59. data/test/jvm/bytecode_test_helper.rb +71 -57
  60. data/test/jvm/cast_test.rb +162 -0
  61. data/test/jvm/constructors_test.rb +48 -0
  62. data/test/jvm/enumerable_test.rb +136 -7
  63. data/test/jvm/example_test.rb +39 -0
  64. data/test/jvm/factory_test.rb +6 -0
  65. data/test/jvm/generics_test.rb +0 -5
  66. data/test/jvm/import_test.rb +81 -0
  67. data/test/jvm/interface_test.rb +113 -0
  68. data/test/jvm/java_typer_test.rb +57 -11
  69. data/test/jvm/jvm_commands_test.rb +24 -0
  70. data/test/jvm/jvm_compiler_test.rb +186 -370
  71. data/test/jvm/macros_test.rb +67 -6
  72. data/test/jvm/main_method_test.rb +1 -1
  73. data/test/jvm/mirror_compilation_test_helper.rb +24 -0
  74. data/test/jvm/new_backend_test_helper.rb +25 -0
  75. data/test/jvm/rescue_test.rb +153 -18
  76. data/test/jvm/string_test.rb +41 -0
  77. data/test/jvm/varargs_test.rb +65 -0
  78. data/test/mirrors/base_type_test.rb +96 -0
  79. data/test/mirrors/bytecode_mirror_test.rb +86 -0
  80. data/test/mirrors/generics_test.rb +776 -0
  81. data/test/mirrors/member_test.rb +69 -0
  82. data/test/mirrors/method_lookup_test.rb +574 -0
  83. data/test/mirrors/mirrors_test.rb +562 -0
  84. data/test/mirrors/simple_async_mirror_loader_test.rb +110 -0
  85. data/test/mirrors/simple_mirror_loader_test.rb +104 -0
  86. data/test/test_helper.rb +2 -1
  87. metadata +244 -217
  88. data/README.txt +0 -59
  89. data/javalib/dynalink-0.2.jar +0 -0
  90. data/lib/mirah/jvm/typer.rb +0 -177
  91. data/lib/mirah/jvm/types/dynamic_type.rb +0 -45
  92. data/lib/mirah/jvm/types/unreachable_type.rb +0 -27
@@ -0,0 +1,973 @@
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
+ require 'mirah/jvm/types'
17
+
18
+ class Java::JavaMethod
19
+ def static?
20
+ java.lang.reflect.Modifier.static?(modifiers)
21
+ end
22
+
23
+ def abstract?
24
+ java.lang.reflect.Modifier.abstract?(modifiers)
25
+ end
26
+ end
27
+
28
+ class BiteScript::ASM::FieldMirror
29
+ def returnType
30
+ self.type
31
+ end
32
+ end
33
+
34
+ module Mirah::JVM::Types
35
+ AST ||= Mirah::AST
36
+
37
+ module ArgumentConversion
38
+ def convert_args(compiler, values, types=nil)
39
+ # TODO boxing/unboxing
40
+ types ||= argument_types
41
+ needs_to_build_varargs_array = false
42
+
43
+ if respond_to?(:varargs?) && varargs?
44
+ non_varargs_types = types[0..-2]
45
+ non_varargs_values = values.first non_varargs_types.size
46
+
47
+ varargs_values = values.to_a.last(values.size - non_varargs_values.size)
48
+ varargs_type = types.last
49
+
50
+ unless varargs_values.length == 1 &&
51
+ varargs_type.compatible?(compiler.inferred_type(varargs_values.first))
52
+ needs_to_build_varargs_array = true
53
+ values = non_varargs_values
54
+ end
55
+ end
56
+
57
+ values_and_types = values.zip(types)
58
+
59
+ values_and_types.each do |value, type|
60
+ compiler.visit(value, true)
61
+ in_type = compiler.inferred_type(value)
62
+ if in_type.primitive? && type != in_type
63
+ in_type.compile_widen(compiler.method, type)
64
+ end
65
+ end
66
+
67
+ if needs_to_build_varargs_array
68
+ compiler.visitVarargsArray(varargs_type, varargs_values)
69
+ end
70
+ end
71
+ end
72
+
73
+ Type.send :include, ArgumentConversion
74
+
75
+ class Intrinsic
76
+ include ArgumentConversion
77
+ attr_reader :name, :argument_types, :return_type
78
+
79
+ def initialize(klass, name, args, type, kind=nil, &block)
80
+ raise ArgumentError, "Block required" unless block_given?
81
+ @class = klass
82
+ @name = name
83
+ @argument_types = args
84
+ @return_type = type
85
+ @block = block
86
+ @kind = kind
87
+ end
88
+
89
+ def kind
90
+ Java::OrgMirahJvmTypes::MemberKind.const_get(@kind)
91
+ end
92
+
93
+ def accept(visitor, expression)
94
+ name = "visit_#{@kind.downcase}".sub(/_op$/,"")
95
+ visitor.send(name, self, expression)
96
+ end
97
+
98
+ def call(builder, ast, expression, *args)
99
+ @block.call(builder, ast, expression, *args)
100
+ end
101
+
102
+ def declaring_class
103
+ @class
104
+ end
105
+
106
+ def constructor?
107
+ false
108
+ end
109
+
110
+ def field?
111
+ false
112
+ end
113
+
114
+ def abstract?
115
+ false
116
+ end
117
+
118
+ def exceptions
119
+ []
120
+ end
121
+
122
+ def varargs?
123
+ false
124
+ end
125
+
126
+ def isVararg
127
+ varargs?
128
+ end
129
+ end
130
+
131
+ class Macro
132
+ java_import 'org.mirah.typer.InlineCode'
133
+ java_import 'org.mirah.typer.NodeBuilder'
134
+ attr_reader :name, :argument_types, :return_type
135
+
136
+ def initialize(klass, name, args, &block)
137
+ raise ArgumentError, "Block required" unless block_given?
138
+ @class = klass
139
+ @name = name
140
+ @argument_types = args
141
+ raise ArgumentError unless args.all?
142
+ @return_type = InlineCode.new(block.to_java(NodeBuilder))
143
+ end
144
+
145
+ def declaring_class
146
+ @class
147
+ end
148
+ end
149
+
150
+ class JavaCallable
151
+ include ArgumentConversion
152
+
153
+ attr_accessor :member
154
+
155
+ def initialize(types, member)
156
+ raise ArgumentError unless types.kind_of?(Mirah::Typer::TypeSystem)
157
+ @types = types
158
+ @member = member
159
+ end
160
+
161
+ def name
162
+ @name ||= @member.name
163
+ end
164
+
165
+ def field?
166
+ false
167
+ end
168
+
169
+ def parameter_types
170
+ @member.parameter_types
171
+ end
172
+
173
+ def synthetic?
174
+ @member.synthetic?
175
+ end
176
+ end
177
+
178
+ class JavaConstructor < JavaCallable
179
+ def argument_types
180
+ @argument_types ||= @member.argument_types.map do |arg|
181
+ if arg.kind_of?(Type) || arg.nil?
182
+ arg
183
+ else
184
+ @types.type(nil, arg)
185
+ end
186
+ end
187
+ end
188
+
189
+ def return_type
190
+ declaring_class
191
+ end
192
+
193
+ def exceptions
194
+ @member.exception_types.map do |exception|
195
+ if exception.kind_of?(Mirah::Typer::ResolvedType)
196
+ exception
197
+ else
198
+ @types.type(nil, exception.class_name)
199
+ end
200
+ end
201
+ end
202
+
203
+ def declaring_class
204
+ @types.type(nil, @member.declaring_class)
205
+ end
206
+
207
+ def type_parameters
208
+ @declaring_class and @declaring_class.jvm_type.type_parameters
209
+ end
210
+
211
+ def call(compiler, ast, expression, parameters=nil, delegate=false)
212
+ target = compiler.inferred_type(ast.target)
213
+ unless delegate
214
+ compiler.method.new target
215
+ compiler.method.dup if expression
216
+ end
217
+ parameters ||= ast.parameters
218
+ convert_args(compiler, parameters)
219
+ compiler.method.invokespecial(
220
+ target,
221
+ "<init>",
222
+ [nil, *@member.argument_types])
223
+ end
224
+
225
+ def constructor?
226
+ true
227
+ end
228
+
229
+ def varargs?
230
+ @member.varargs?
231
+ end
232
+
233
+ def isVararg
234
+ varargs?
235
+ end
236
+
237
+ def accept(visitor, expression)
238
+ visitor.visitConstructor(self, expression)
239
+ end
240
+
241
+ def kind
242
+ Java::OrgMirahJvmTypes::MemberKind::CONSTRUCTOR
243
+ end
244
+ end
245
+
246
+ class JavaMethod < JavaConstructor
247
+ def return_type
248
+ @return_type ||= begin
249
+ if void?
250
+ @types.type(nil, 'void')
251
+ else
252
+ @types.type(nil, @member.return_type)
253
+ end
254
+ end
255
+ end
256
+
257
+ def static?
258
+ @member.static?
259
+ end
260
+
261
+ def abstract?
262
+ @member.abstract?
263
+ end
264
+
265
+ def type_parameters
266
+ @member.type_parameters
267
+ end
268
+
269
+ def void?
270
+ return_type = @member.return_type
271
+ return true if return_type.nil?
272
+ if return_type.respond_to?(:descriptor) && return_type.descriptor == 'V'
273
+ return true
274
+ end
275
+ false
276
+ end
277
+
278
+ def constructor?
279
+ false
280
+ end
281
+
282
+ def accept(visitor, expression)
283
+ if self.static?
284
+ visitor.visitStaticMethodCall(self, expression)
285
+ else
286
+ visitor.visitMethodCall(self, expression)
287
+ end
288
+ end
289
+
290
+ def kind
291
+ if self.static?
292
+ Java::OrgMirahJvmTypes::MemberKind::STATIC_METHOD
293
+ else
294
+ Java::OrgMirahJvmTypes::MemberKind::METHOD
295
+ end
296
+ end
297
+
298
+ def call(compiler, ast, expression, parameters=nil)
299
+ target = compiler.inferred_type(ast.target)
300
+ compiler.visit(ast.target, true)
301
+
302
+ # if expression, void methods return the called object,
303
+ # for consistency and chaining
304
+ # TODO: inference phase needs to track that signature is
305
+ # void but actual type is callee
306
+ if expression && void?
307
+ compiler.method.dup
308
+ end
309
+
310
+ parameters ||= ast.parameters
311
+ convert_args(compiler, parameters)
312
+ if target.interface?
313
+ compiler.method.invokeinterface(
314
+ target,
315
+ name,
316
+ [@member.return_type, *@member.argument_types])
317
+ else
318
+ compiler.method.invokevirtual(
319
+ target,
320
+ name,
321
+ [@member.return_type, *@member.argument_types])
322
+ end
323
+
324
+ if expression && !void?
325
+ # Insert a cast if the inferred type and actual type differ. This is part of generics support.
326
+ inferred_return_type = compiler.inferred_type(ast)
327
+ if !inferred_return_type.assignableFrom(return_type)
328
+ compiler.method.checkcast(inferred_return_type)
329
+ end
330
+ end
331
+
332
+ unless expression || void?
333
+ return_type.pop(compiler.method)
334
+ end
335
+ end
336
+
337
+ def call_special(compiler, target, target_type, parameters, expression)
338
+ target_type ||= compiler.inferred_type(target)
339
+ compiler.visit(target, true)
340
+
341
+ # if expression, void methods return the called object,
342
+ # for consistency and chaining
343
+ # TODO: inference phase needs to track that signature is
344
+ # void but actual type is callee
345
+ if expression && void?
346
+ compiler.method.dup
347
+ end
348
+
349
+ convert_args(compiler, parameters)
350
+ if target_type.interface?
351
+ raise "interfaces should not receive call_special"
352
+ else
353
+ compiler.method.invokespecial(
354
+ target_type,
355
+ name,
356
+ [@member.return_type, *@member.argument_types])
357
+ end
358
+
359
+ unless expression || void?
360
+ return_type.pop(compiler.method)
361
+ end
362
+ end
363
+ end
364
+
365
+ class JavaStaticMethod < JavaMethod
366
+ def call(compiler, ast, expression, parameters=nil)
367
+ target = declaring_class
368
+ parameters ||= ast.parameters
369
+ convert_args(compiler, parameters)
370
+ compiler.method.invokestatic(
371
+ target,
372
+ name,
373
+ [@member.return_type, *@member.argument_types])
374
+ # if expression, void static methods return null, for consistency
375
+ # TODO: inference phase needs to track that signature is void
376
+ # but actual type is null object
377
+ compiler.method.aconst_null if expression && void?
378
+ return_type.pop(compiler.method) unless expression || void?
379
+ end
380
+
381
+ def accept(visitor, expression)
382
+ visitor.visitStaticMethodCall(self, expression)
383
+ end
384
+
385
+ def kind
386
+ Java::OrgMirahJvmTypes::MemberKind::STATIC_METHOD
387
+ end
388
+ end
389
+
390
+ class JavaDynamicMethod < JavaMethod
391
+ def initialize(type_system, name, *argument_types)
392
+ super(type_system, nil)
393
+ @name = name
394
+ @argument_types = argument_types
395
+ end
396
+
397
+ def return_type
398
+ @types.type(nil, 'dynamic')
399
+ end
400
+
401
+ def declaring_class
402
+ java.lang.Object
403
+ end
404
+
405
+ def argument_types
406
+ @argument_types
407
+ end
408
+
409
+ def call(compiler, ast, expression, parameters=nil)
410
+ unless compiler.respond_to?(:supports_invokedynamic?) && compiler.supports_invokedynamic?
411
+ raise Mirah::MirahError, "Target JVM version: #{compiler.target_jvm_version} doesn't support invoke dynamic"
412
+ end
413
+ target = compiler.inferred_type(ast.target)
414
+ compiler.visit(ast.target, true)
415
+
416
+ parameters ||= ast.parameters
417
+ parameters.each do |param|
418
+ compiler.visit(param, true)
419
+ end
420
+ handle = compiler.method.h_invokestatic(
421
+ org.dynalang.dynalink.DefaultBootstrapper,
422
+ "bootstrap",
423
+ java.lang.invoke.CallSite,
424
+ java.lang.invoke.MethodHandles::Lookup,
425
+ java.lang.String,
426
+ java.lang.invoke.MethodType)
427
+ compiler.method.invokedynamic(
428
+ "dyn:callPropWithThis:#{name}",
429
+ [return_type, target, *@argument_types],
430
+ handle)
431
+
432
+ unless expression
433
+ return_type.pop(compiler.method)
434
+ end
435
+ end
436
+ end
437
+
438
+ class JavaFieldAccessor < JavaMethod
439
+ def field?
440
+ true
441
+ end
442
+
443
+ def return_type
444
+ @types.type(nil, @member.type)
445
+ end
446
+
447
+ def public?
448
+ @member.public?
449
+ end
450
+
451
+ def final?
452
+ @member.final?
453
+ end
454
+ end
455
+
456
+ class JavaFieldGetter < JavaFieldAccessor
457
+ def argument_types
458
+ []
459
+ end
460
+
461
+ def call(compiler, ast, expression, parameters=nil)
462
+ target = compiler.inferred_type(ast.target)
463
+
464
+ # TODO: assert that no args are being passed, though that should have failed lookup
465
+
466
+ if expression
467
+ if @member.static?
468
+ compiler.method.getstatic(target, name, @member.type)
469
+ else
470
+ compiler.visit(ast.target, true)
471
+ compiler.method.getfield(target, name, @member.type)
472
+ end
473
+ end
474
+ end
475
+
476
+ def accept(visitor, expression)
477
+ if self.static?
478
+ visitor.visitStaticFieldAccess(self, expression)
479
+ else
480
+ visitor.visitFieldAccess(self, expression)
481
+ end
482
+ end
483
+
484
+ def kind
485
+ if self.static?
486
+ Java::OrgMirahJvmTypes::MemberKind::STATIC_FIELD_ACCESS
487
+ else
488
+ Java::OrgMirahJvmTypes::MemberKind::FIELD_ACCESS
489
+ end
490
+ end
491
+ end
492
+
493
+ class JavaFieldSetter < JavaFieldAccessor
494
+ def return_type
495
+ @types.type(nil, @member.type)
496
+ end
497
+
498
+ def argument_types
499
+ [@types.type(nil, @member.type)]
500
+ end
501
+
502
+ def call(compiler, ast, expression, parameters=nil)
503
+ target = compiler.inferred_type(ast.target)
504
+
505
+ # TODO: assert that no args are being passed, though that should have failed lookup
506
+
507
+ parameters ||= ast.parameters
508
+ if @member.static?
509
+ convert_args(compiler, parameters)
510
+ compiler.method.dup if expression
511
+ compiler.method.putstatic(target, name, @member.type)
512
+ else
513
+ compiler.visit(ast.target, true)
514
+ convert_args(compiler, parameters)
515
+ compiler.method.dup_x2 if expression
516
+ compiler.method.putfield(target, name, @member.type)
517
+ end
518
+ end
519
+
520
+ def accept(visitor, expression)
521
+ if self.static?
522
+ visitor.visitStaticFieldAssign(self, expression)
523
+ else
524
+ visitor.visitFieldAssign(self, expression)
525
+ end
526
+ end
527
+
528
+ def kind
529
+ if self.static?
530
+ Java::OrgMirahJvmTypes::MemberKind::STATIC_FIELD_ASSIGN
531
+ else
532
+ Java::OrgMirahJvmTypes::MemberKind::FIELD_ASSIGN
533
+ end
534
+ end
535
+ end
536
+
537
+ class MirahMember
538
+ attr_reader :name, :argument_types, :declaring_class, :return_type
539
+ attr_reader :exception_types
540
+
541
+ def initialize(klass, name, args, return_type, static, exceptions)
542
+ if return_type.name == 'void' || return_type.name == ':unreachable'
543
+ return_type = nil
544
+ end
545
+ @declaring_class = klass
546
+ @name = name
547
+ @argument_types = args
548
+ @return_type = return_type
549
+ @static = static
550
+ @exception_types = exceptions || []
551
+ end
552
+
553
+ def static?
554
+ @static
555
+ end
556
+
557
+ def abstract?
558
+ @declaring_class.interface?
559
+ end
560
+
561
+ def varargs?
562
+ false
563
+ end
564
+
565
+ def isVararg
566
+ varargs?
567
+ end
568
+ end
569
+
570
+ class Type
571
+ java_import "org.mirah.jvm.types.JVMMethod" rescue nil
572
+
573
+ def method_listeners
574
+ if meta?
575
+ unmeta.method_listeners
576
+ else
577
+ @method_listeners ||= {}
578
+ end
579
+ end
580
+
581
+ def method_updated(name)
582
+ listeners = method_listeners[name]
583
+ listeners.values.each do |l|
584
+ if l.kind_of?(Proc)
585
+ l.call(name)
586
+ else
587
+ l.method_updated(name)
588
+ end
589
+ end if listeners
590
+ end
591
+
592
+ def add_method_listener(name, listener=nil, &block)
593
+ listeners = method_listeners[name] ||= {}
594
+ if listener
595
+ unless listener.respond_to?(:method_updated) || listener.kind_of?(Proc)
596
+ raise "Invalid listener"
597
+ end
598
+ listeners[listener] = listener
599
+ else
600
+ listeners[block] = block
601
+ end
602
+ if !self.meta? && jvm_type && super_class_valid?
603
+ superclass.add_method_listener(name, self)
604
+ end
605
+ interfaces.each {|i| i.add_method_listener(name, self) unless i.isError}
606
+ end
607
+
608
+ # TODO take a scope and check visibility
609
+ def find_callable_macros(name)
610
+ macros = find_callable_macros2 name
611
+ macros.concat collect_up_interface_tree {|interface| interface.declared_macros(name) }
612
+ macros
613
+ end
614
+
615
+ def find_callable_macros2(name)
616
+ collect_up_inheritance_tree {|type| type.declared_macros name }
617
+ end
618
+
619
+ def find_callable_static_methods(name)
620
+ collect_up_inheritance_tree { |type| type.declared_class_methods(name) }
621
+ end
622
+
623
+ # TODO take a scope and check visibility
624
+ def find_callable_methods(name, include_interfaces=false, &proc)
625
+ if block_given?
626
+ add_method_listener(name) {proc.call(find_callable_methods(name))}
627
+ proc.call(find_callable_methods(name))
628
+ return
629
+ end
630
+
631
+ methods = find_callable_methods2 name
632
+
633
+ if self.interface? || include_interfaces # TODO || self.abstract?
634
+ methods.concat collect_up_interface_tree { |interface| interface.declared_instance_methods(name) }
635
+ end
636
+ methods
637
+ end
638
+
639
+ def find_callable_methods2(name)
640
+ collect_up_inheritance_tree { |type| type.declared_instance_methods(name) }
641
+ end
642
+
643
+ def get_method(name, args)
644
+ method = find_method(self, name, args, nil, meta?)
645
+ unless method
646
+ # Allow constant narrowing for assignment methods
647
+ if name =~ /=$/ && args[-1].respond_to?(:narrow!)
648
+ if args[-1].narrow!
649
+ method = find_method(self, name, args, meta?)
650
+ end
651
+ end
652
+ end
653
+ method
654
+ end
655
+
656
+ def constructor(*types)
657
+ begin
658
+ constructor = jvm_type.getConstructor(*bitescript_signatures(types))
659
+ return JavaConstructor.new(@type_system, constructor) if constructor
660
+ rescue => ex
661
+ log("#{ex.message}\n#{ex.backtrace.join("\n")}")
662
+ end
663
+ raise NameError, "No constructor #{name}(#{types.join ', '})"
664
+ end
665
+
666
+ def java_method(name, *types)
667
+ intrinsic = intrinsics[name][types]
668
+ return intrinsic if intrinsic
669
+ jvm_types = types.map {|type| type.jvm_type}
670
+
671
+ return JavaDynamicMethod.new(@type_system, name, *jvm_types) if dynamic?
672
+
673
+ begin
674
+ method = jvm_type.getDeclaredMethod(name, *bitescript_signatures(types)) if jvm_type
675
+
676
+ if method.nil? && superclass
677
+ method = superclass.java_method(name, *types) rescue nil
678
+ end
679
+
680
+ if method.nil? && jvm_type && jvm_type.abstract?
681
+ interfaces.each do |interface|
682
+ method = interface.java_method(name, *types) rescue nil
683
+ break if method
684
+ end
685
+ end
686
+
687
+ return method if method.kind_of?(JavaCallable)
688
+ if method && method.static? == meta?
689
+ return wrap_jvm_method method
690
+ end
691
+ rescue => ex
692
+ log("#{ex.message}\n#{ex.backtrace.join("\n")}")
693
+ end
694
+ raise NameError, "No method #{self.name}.#{name}(#{types.join ', '})"
695
+ end
696
+
697
+ def declared_instance_methods(name=nil)
698
+ all_declared_jvm_methods(name).reject{ |method| method.static? && !method.synthetic? } +
699
+ (meta? ? unmeta : self).declared_intrinsics(name)
700
+ end
701
+
702
+ def declared_class_methods(name=nil)
703
+ all_declared_jvm_methods(name).select{ |method| method.static? && !method.synthetic? } +
704
+ meta.declared_intrinsics(name)
705
+ end
706
+
707
+ def declared_constructors
708
+ jvm_type.getConstructors.map do |method|
709
+ JavaConstructor.new(@type_system, method)
710
+ end
711
+ end
712
+
713
+ def field_getter(name)
714
+ field = jvm_field(name)
715
+ return nil unless field
716
+
717
+ JavaFieldGetter.new(@type_system, field)
718
+ end
719
+
720
+ def field_setter(name)
721
+ field = jvm_field(name)
722
+ return nil unless field
723
+
724
+ JavaFieldSetter.new(@type_system, field)
725
+ end
726
+
727
+ def inner_class_getter(name)
728
+ full_name = "#{self.name}$#{name}"
729
+ inner_class = @type_system.type(nil, full_name) rescue nil
730
+ return unless inner_class
731
+
732
+ inner_class.inner_class = true
733
+ macro = Macro.new(self, name, []) do |call, typer|
734
+ Mirah::AST::Constant.new(call.position, Mirah::AST::SimpleString.new(call.position, full_name))
735
+ end
736
+ intrinsics[name][[]] = macro
737
+ end
738
+
739
+ def getDeclaredFields
740
+ @member.getDeclaredFields.to_java(JVMMethod)
741
+ end
742
+
743
+ def getDeclaredField(name)
744
+ @member.getDeclaredField(name)
745
+ end
746
+
747
+ def hasStaticField(name)
748
+ f = getDeclaredField(name)
749
+ f && f.static?
750
+ end
751
+
752
+ protected
753
+
754
+ def find_interfaces
755
+ collect_up_inheritance_tree {|type| type.interfaces }
756
+ end
757
+
758
+ def collect_up_interface_tree &block
759
+ interfaces = find_interfaces
760
+ things = []
761
+ seen = {}
762
+ until interfaces.empty?
763
+ interface = interfaces.pop
764
+ next if seen[interface]
765
+ seen[interface] = true
766
+ interfaces.concat(interface.interfaces)
767
+ new_things = block.call interface
768
+ things.concat new_things if new_things
769
+ end
770
+ things
771
+ end
772
+
773
+ def collect_up_inheritance_tree(&block)
774
+ things = []
775
+ new_things = block.call(self)
776
+ things.concat new_things if new_things
777
+ if super_class_valid?
778
+ things.concat superclass.collect_up_inheritance_tree(&block)
779
+ end
780
+ things
781
+ end
782
+
783
+ private
784
+
785
+ def super_class_valid?
786
+ superclass && !superclass.error?
787
+ end
788
+
789
+ def all_declared_jvm_methods(name=nil)
790
+ return [] if !jvm_type || (meta? ? unmeta : self).array?
791
+
792
+ jvm_type.getDeclaredMethods(name).map { |method| wrap_jvm_method method }
793
+ end
794
+
795
+ def wrap_jvm_method method
796
+ if (method.static? && !method.synthetic?)
797
+ JavaStaticMethod.new(@type_system, method)
798
+ else
799
+ JavaMethod.new(@type_system, method)
800
+ end
801
+ end
802
+
803
+ def jvm_field(name)
804
+ return nil unless jvm_type
805
+ jvm_type.getField(name)
806
+ end
807
+
808
+ def bitescript_signatures types
809
+ types.map {|type| BiteScript::Signature.class_id(type)}
810
+ end
811
+ end
812
+
813
+ class TypeDefinition
814
+ java_import "org.mirah.jvm.types.JVMMethod" rescue nil
815
+
816
+ def java_method(name, *types)
817
+ method = first_matching instance_methods[name], types
818
+ return method if method
819
+ intrinsic = intrinsics[name][types]
820
+ return intrinsic if intrinsic
821
+ raise NameError, "No method #{self.name}.#{name}(#{types.join ', '})"
822
+ end
823
+
824
+ def java_static_method(name, *types)
825
+ method = first_matching static_methods[name], types
826
+ return method if method
827
+ intrinsic = meta.intrinsics[name][types]
828
+ return intrinsic if intrinsic
829
+ raise NameError, "No method #{self.name}.#{name}(#{types.join ', '})"
830
+ end
831
+
832
+ def constructor(*types)
833
+ constructor = first_matching constructors, types
834
+ return constructor if constructor
835
+ raise NameError, "No constructor #{name}(#{types.join ', '})"
836
+ end
837
+
838
+ def declared_instance_methods(name=nil)
839
+ declared_methods self, instance_methods, name
840
+ end
841
+
842
+ def declared_class_methods(name=nil)
843
+ declared_methods meta, static_methods, name
844
+ end
845
+
846
+ def constructors
847
+ if @constructors.nil?
848
+ @constructors = []
849
+ declare_method('initialize', [], self, [])
850
+ @have_default_constructor = true
851
+ end
852
+ @constructors
853
+ end
854
+ alias :declared_constructors :constructors
855
+
856
+ def instance_methods
857
+ @instance_methods ||= Hash.new {|h, k| h[k] = []}
858
+ end
859
+
860
+ def static_methods
861
+ @static_methods ||= Hash.new {|h, k| h[k] = []}
862
+ end
863
+
864
+ def getDeclaredFields
865
+ @fields.values.to_java(JVMMethod)
866
+ end
867
+
868
+ def getDeclaredField(name)
869
+ @fields[name]
870
+ end
871
+
872
+ def hasStaticField(name)
873
+ f = getDeclaredField(name)
874
+ f && f.static?
875
+ end
876
+
877
+ def declared_fields
878
+ @fields ||= {}
879
+ end
880
+
881
+ def declare_field(name, type, static)
882
+ declared_fields[name] ||= MirahMember.new(self, name, [], type, static, [])
883
+ end
884
+
885
+ def declare_method(name, arguments, type, exceptions)
886
+ raise "Bad args" unless arguments.all?
887
+ if type.isError
888
+ instance_methods.delete(name)
889
+ method_updated(name)
890
+ return
891
+ end
892
+ member = MirahMember.new(self, name, arguments, type, false, exceptions)
893
+ if name == 'initialize'
894
+ # The ordering is important here:
895
+ # The first call to constructors initializes @have_default_constructor.
896
+ if constructors.size == 1 && @have_default_constructor
897
+ constructors.clear
898
+ @have_default_constructor = false
899
+ elsif constructors.size > 1 && @have_default_constructor
900
+ raise "Invalid state: default constructor but #{constructors.size} constructors"
901
+ end
902
+ constructors << JavaConstructor.new(@type_system, member)
903
+ else
904
+ instance_methods[name] << JavaMethod.new(@type_system, member)
905
+ end
906
+ method_updated(name)
907
+ end
908
+
909
+ def declare_static_method(name, arguments, type, exceptions)
910
+ if type.isError
911
+ static_methods.delete(name)
912
+ else
913
+ member = MirahMember.new(self, name, arguments, type, true, exceptions)
914
+ static_methods[name] << JavaStaticMethod.new(@type_system, member)
915
+ end
916
+ method_updated(name)
917
+ end
918
+
919
+ def interface?
920
+ false
921
+ end
922
+
923
+ def field_getter(name)
924
+ nil
925
+ end
926
+
927
+ def field_setter(name)
928
+ nil
929
+ end
930
+
931
+ private
932
+
933
+ def declared_methods target, method_hash, name
934
+ # should the declared intrinsics be first here? nh
935
+ target.declared_intrinsics(name) +
936
+ if name.nil?
937
+ method_hash.values.flatten
938
+ else
939
+ method_hash[name]
940
+ end
941
+ end
942
+
943
+ def first_matching method_list, types
944
+ method_list.find {|m| m.argument_types == types}
945
+ end
946
+ end
947
+
948
+ class TypeDefMeta
949
+ def constructor(*args)
950
+ unmeta.constructor(*args)
951
+ end
952
+
953
+ def java_method(*args)
954
+ unmeta.java_static_method(*args)
955
+ end
956
+
957
+ def declared_class_methods(name=nil)
958
+ unmeta.declared_class_methods(name)
959
+ end
960
+
961
+ def declared_instance_methods(name=nil)
962
+ unmeta.declared_instance_methods(name)
963
+ end
964
+
965
+ def field_getter(name)
966
+ nil
967
+ end
968
+
969
+ def field_setter(name)
970
+ nil
971
+ end
972
+ end
973
+ end