mirah 0.1.0.pre-java → 0.1.1-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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