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
@@ -14,36 +14,29 @@
14
14
  # limitations under the License.
15
15
 
16
16
  module Mirah::JVM::Types
17
- Boolean = BooleanType.new('boolean', java.lang.Boolean)
18
- Byte = IntegerType.new('byte', java.lang.Byte)
19
- Char = IntegerType.new('char', java.lang.Character)
20
- Short = IntegerType.new('short', java.lang.Short)
21
- Int = IntegerType.new('int', java.lang.Integer)
22
- Long = LongType.new('long', java.lang.Long)
23
- Float = FloatType.new('float', java.lang.Float)
24
- Double = DoubleType.new('double', java.lang.Double)
25
-
26
- # TODO these shouldn't be constants. They should be loaded from
27
- # the compilation class path.
28
- Object = Type.new(BiteScript::ASM::ClassMirror.load('java.lang.Object'))
29
- ClassType = Type.new(BiteScript::ASM::ClassMirror.load('java.lang.Class'))
30
- String = StringType.new(
31
- BiteScript::ASM::ClassMirror.load('java.lang.String'))
32
- Iterable = IterableType.new(
33
- BiteScript::ASM::ClassMirror.load('java.lang.Iterable'))
34
-
35
- Void = VoidType.new
36
- Unreachable = UnreachableType.new
37
- Null = NullType.new
38
-
39
- WIDENING_CONVERSIONS = {
40
- Byte => [Byte, Short, Int, Long, Float, Double],
41
- Short => [Short, Int, Long, Float, Double],
42
- Char => [Char, Int, Long, Float, Double],
43
- Int => [Int, Long, Float, Double],
44
- Long => [Long, Float, Double],
45
- Float => [Float, Double],
46
- Double => [Double]
47
- }
48
- TYPE_ORDERING = [Byte, Short, Int, Long, Float, Double]
49
- end
17
+ class TypeFactory
18
+ def create_basic_types
19
+ @known_types.update(
20
+ 'boolean' => BooleanType.new(self, 'boolean', java.lang.Boolean),
21
+ 'byte' => IntegerType.new(self, 'byte', java.lang.Byte),
22
+ 'char' => IntegerType.new(self, 'char', java.lang.Character),
23
+ 'short' => IntegerType.new(self, 'short', java.lang.Short),
24
+ 'int' => IntegerType.new(self, 'int', java.lang.Integer),
25
+ 'long' => LongType.new(self, 'long', java.lang.Long),
26
+ 'float' => FloatType.new(self, 'float', java.lang.Float),
27
+ 'double' => DoubleType.new(self, 'double', java.lang.Double)
28
+ )
29
+ @known_types['fixnum'] = @known_types['int']
30
+ @known_types['Object'] = type(nil, 'java.lang.Object')
31
+ @known_types['string'] = @known_types['String'] = @known_types['java.lang.String'] =
32
+ StringType.new(self, get_mirror('java.lang.String'))
33
+ type(nil, 'java.lang.Class')
34
+ @known_types['Iterable'] = @known_types['java.lang.Iterable'] =
35
+ IterableType.new(self, get_mirror('java.lang.Iterable'))
36
+ @known_types['void'] = VoidType.new(self)
37
+ @known_types['null'] = NullType.new(self)
38
+ @known_types['implicit_nil'] = ImplicitNilType.new(self)
39
+ @known_types['dynamic'] = DynamicType.new(self)
40
+ end
41
+ end
42
+ end
@@ -18,7 +18,7 @@ class BiteScript::MethodBuilder
18
18
  iconst_m1
19
19
  ixor
20
20
  end
21
-
21
+
22
22
  def lnot
23
23
  # TODO would any of these be faster?
24
24
  # iconst_m1; i2l
@@ -0,0 +1,15 @@
1
+ module Mirah
2
+ module JVM
3
+ module Types
4
+ class BlockType < Type
5
+ def initialize
6
+ super(':block', nil)
7
+ end
8
+
9
+ def isBlock
10
+ true
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -28,16 +28,20 @@ module Mirah::JVM::Types
28
28
  builder.invokestatic box_type, "valueOf", [box_type, self]
29
29
  end
30
30
 
31
+ def box_type
32
+ @type_system.type(nil, 'java.lang.Boolean')
33
+ end
34
+
31
35
  def add_intrinsics
32
36
  args = [math_type]
33
37
  add_method('==', args, ComparisonIntrinsic.new(self, '==', :eq, args))
34
38
  add_method('!=', args, ComparisonIntrinsic.new(self, '!=', :ne, args))
35
39
  end
36
-
40
+
37
41
  def math_type
38
- Boolean
42
+ @type_system.type(nil, 'boolean')
39
43
  end
40
-
44
+
41
45
  # same as NumberType's
42
46
  def compile_boolean_operator(compiler, op, negated, call, label)
43
47
  # Promote the target or the argument if necessary
@@ -62,4 +66,4 @@ module Mirah::JVM::Types
62
66
  builder.send "if_icmp#{op}", label
63
67
  end
64
68
  end
65
- end
69
+ end
@@ -2,11 +2,10 @@ module Mirah
2
2
  module JVM
3
3
  module Types
4
4
  class DynamicType < Type
5
- ObjectType = Type.new(BiteScript::ASM::ClassMirror.for_name('java.lang.Object'))
6
-
7
- def initialize
5
+ def initialize(types)
8
6
  # For naming, bytecode purposes, we are an Object
9
- @name = "java.lang.Object"
7
+ super(types, "java.lang.Object")
8
+ @object_type ||= types.type(nil, 'java.lang.Object')
10
9
  end
11
10
 
12
11
  def basic_type
@@ -14,17 +13,17 @@ module Mirah
14
13
  end
15
14
 
16
15
  def is_parent(other)
17
- ObjectType.assignable_from?(other)
16
+ @object_type.assignable_from?(other)
18
17
  end
19
18
 
20
19
  def assignable_from?(other)
21
- ObjectType.assignable_from?(other)
20
+ @object_type.assignable_from?(other)
22
21
  end
23
22
 
24
23
  def jvm_type
25
24
  java.lang.Object
26
25
  end
27
-
26
+
28
27
  def full_name
29
28
  "dynamic"
30
29
  end
@@ -32,15 +31,15 @@ module Mirah
32
31
  def dynamic?
33
32
  true
34
33
  end
35
-
34
+
36
35
  def superclass
37
- ObjectType.superclass
36
+ @object_type
38
37
  end
39
-
40
- def interfaces
41
- ObjectType.interfaces
38
+
39
+ def interfaces(include_parent=true)
40
+ @object_type.interfaces
42
41
  end
43
42
  end
44
43
  end
45
44
  end
46
- end
45
+ end
@@ -20,7 +20,7 @@ module Mirah::JVM::Types
20
20
  code = intrinsics['each'][arg_types].return_type
21
21
  code.inline(transformer, call)
22
22
  end
23
-
23
+
24
24
  def add_enumerable_macros
25
25
  all_proc = proc do |transformer, call|
26
26
  if !call.block
@@ -31,15 +31,15 @@ module Mirah::JVM::Types
31
31
  # block and attach it to the real call.
32
32
  call.block = transformer.eval("foo {|#{var}| #{var}}").block
33
33
  end
34
-
34
+
35
35
  # Now that we've got a block we can transform it into a Loop.
36
36
  forloop = expand_each(transformer, call)
37
-
37
+
38
38
  # Start adding stuff to the loop.
39
39
  # At the beginning of the loop we create a temp initialized to true
40
40
  all = transformer.tmp
41
41
  forloop.init << transformer.eval("#{all} = true")
42
-
42
+
43
43
  # Now we want to wrap the body of the loop. Start off by using
44
44
  # foo as a placeholder.
45
45
  body = transformer.eval(
@@ -48,7 +48,7 @@ module Mirah::JVM::Types
48
48
  body.condition.predicate = call.block.body
49
49
  # And finally patch the new body back into the forloop.
50
50
  forloop.body = call.block.body.parent = body
51
-
51
+
52
52
  # Loops don't have a return value, so we need somewhere to
53
53
  # put the result.
54
54
  result = Mirah::AST::Body.new(call.parent, call.position)
@@ -69,7 +69,7 @@ module Mirah::JVM::Types
69
69
  "if foo;#{any} = true;break;end", '', forloop)
70
70
  body.condition.predicate = call.block.body
71
71
  forloop.body = call.block.body.parent = body
72
-
72
+
73
73
  result = Mirah::AST::Body.new(call.parent, call.position)
74
74
  result << forloop << transformer.eval("#{any}", '', nil, any)
75
75
  end
@@ -77,4 +77,4 @@ module Mirah::JVM::Types
77
77
  add_macro('any?', Mirah::AST.block_type, &any_proc)
78
78
  end
79
79
  end
80
- end
80
+ end
@@ -62,22 +62,27 @@ module Mirah::JVM::Types
62
62
  end
63
63
 
64
64
  def declared_instance_methods(name=nil)
65
- __combine_methods(__getobj__.declared_instance_methods)
65
+ __combine_methods(__getobj__.declared_instance_methods, name)
66
66
  end
67
67
 
68
68
  def declared_class_methods(name=nil)
69
- __combine_methods(__getobj__.declared_class_methods)
69
+ __combine_methods(__getobj__.declared_class_methods, name)
70
70
  end
71
71
 
72
- def __combine_methods(basic_methods)
72
+ def find_callable_methods(name, include_interfaces=false)
73
+ __combine_methods(__getobj__.find_callable_methods(name, include_interfaces), name)
74
+ end
75
+
76
+ def __combine_methods(basic_methods, name)
73
77
  methods = {}
74
78
  basic_methods.each do |method|
75
- key = [method.name, method.parameter_types, method.return_type]
79
+ key = [method.name, method.argument_types, method.return_type]
76
80
  methods[key] = method
77
81
  end
78
82
  @static_includes.each do |type|
79
83
  type.declared_class_methods.each do |method|
80
- key = [method.name, method.parameter_types, method.return_type]
84
+ next if name && method.name != name
85
+ key = [method.name, method.argument_types, method.return_type]
81
86
  methods[key] ||= method
82
87
  end
83
88
  end
@@ -98,4 +103,4 @@ module Mirah::JVM::Types
98
103
  ExtendedType.new(self).include(type)
99
104
  end
100
105
  end
101
- end
106
+ end
@@ -16,32 +16,35 @@
16
16
  require 'jruby'
17
17
  require 'mirah/jvm/types/source_mirror'
18
18
  module Mirah::JVM::Types
19
- class TypeFactory
20
- BASIC_TYPES = {
21
- "boolean" => Boolean,
22
- "byte" => Byte,
23
- "char" => Char,
24
- "short" => Short,
25
- "int" => Int,
26
- "long" => Long,
27
- "float" => Float,
28
- "double" => Double,
29
- "fixnum" => Int,
30
- "string" => String,
31
- "java.lang.String" => String,
32
- "String" => String,
33
- "java.lang.Object" => Object,
34
- "Object" => Object,
35
- "java.lang.Class" => ClassType,
36
- "java.lang.Iterable" => Iterable,
37
- "Iterable" => Iterable,
38
- "void" => Void,
39
- "notype" => Void,
40
- "null" => Null,
41
- "dynamic" => DynamicType.new
42
- }.freeze
43
- java_import 'java.net.URLClassLoader'
19
+ java_import 'org.mirah.typer.simple.SimpleTypes'
20
+ class TypeFactory < SimpleTypes
21
+ java_import 'org.mirah.typer.AssignableTypeFuture'
22
+ java_import 'org.mirah.typer.PickFirst'
23
+ java_import 'org.mirah.typer.BaseTypeFuture'
24
+ #java_import 'org.mirah.typer.BlockType'
25
+ java_import 'org.mirah.typer.ErrorType'
26
+ java_import 'org.mirah.typer.GenericTypeFuture'
27
+ java_import 'org.mirah.typer.MethodFuture'
28
+ java_import 'org.mirah.typer.MethodType'
29
+ java_import 'org.mirah.typer.SimpleFuture'
30
+ java_import 'org.mirah.typer.TypeFuture'
31
+ java_import 'org.mirah.typer.TypeSystem'
32
+ java_import 'org.mirah.typer.NarrowingTypeFuture'
33
+ java_import 'mirah.lang.ast.ClassDefinition'
34
+ java_import 'mirah.lang.ast.InterfaceDeclaration'
35
+ java_import 'mirah.lang.ast.Script'
36
+ java_import 'mirah.lang.ast.SimpleString'
37
+ include TypeSystem
38
+ include Mirah::Logging::Logged
39
+
40
+ begin
41
+ java_import 'org.mirah.builtins.Builtins'
42
+ rescue NameError
43
+ # We might be trying to compile mirah-builtins.jar, so just continue.
44
+ Builtins = nil
45
+ end
44
46
 
47
+ java_import 'java.net.URLClassLoader'
45
48
  attr_accessor :package
46
49
  attr_reader :known_types
47
50
 
@@ -53,10 +56,13 @@ module Mirah::JVM::Types
53
56
  end
54
57
 
55
58
  def initialize
59
+ super(":unused")
56
60
  @known_types = ParanoidHash.new
57
- @known_types.update(BASIC_TYPES)
61
+ @anonymous_classes = Hash.new {|h, k| h[k] = 0}
58
62
  @declarations = []
59
63
  @mirrors = {}
64
+ @futures = {}
65
+ create_basic_types
60
66
  end
61
67
 
62
68
  def initialize_copy(other)
@@ -65,6 +71,465 @@ module Mirah::JVM::Types
65
71
  value.basic_type.kind_of?(Mirah::JVM::Types::TypeDefinition)
66
72
  end
67
73
  @declarations = []
74
+ @futures = {}
75
+ end
76
+
77
+ def maybe_initialize_builtins(compiler)
78
+ if Builtins
79
+ begin
80
+ Builtins.initialize_builtins(compiler)
81
+ rescue NativeException => ex
82
+ error("Error initializing builtins", ex.cause)
83
+ rescue => ex
84
+ error("Error initializing builtins: #{ex.message}\n\t#{ex.backtrace.join("\n\t")}")
85
+ end
86
+ else
87
+ warning "Unable to initialize builtins"
88
+ end
89
+ end
90
+
91
+ def wrap(resolved_type)
92
+ future = BaseTypeFuture.new(nil)
93
+ future.resolved(resolved_type) if resolved_type
94
+ future
95
+ end
96
+
97
+ def cache_and_wrap(resolved_type)
98
+ @futures[resolved_type.name] ||= wrap(resolved_type)
99
+ end
100
+
101
+ def cache_and_wrap_type(name)
102
+ @futures[name] ||= begin
103
+ type = type(nil, name)
104
+ wrapper = wrap(type)
105
+ wrapper.resolved(ErrorType.new([["Cannot find class #{name}"]])) if type.nil?
106
+ wrapper
107
+ end
108
+ end
109
+
110
+ # TypeSystem methods
111
+ def addDefaultImports(scope)
112
+ scope.import('java.lang.*', '*')
113
+ end
114
+
115
+ def getNullType; cache_and_wrap_type('null') end
116
+ def getImplicitNilType; cache_and_wrap_type('implicit_nil') end
117
+ def getVoidType; cache_and_wrap_type('void') end
118
+ def getBaseExceptionType; cache_and_wrap_type('java.lang.Throwable') end
119
+ def getDefaultExceptionType; cache_and_wrap_type('java.lang.Exception') end
120
+ def getHashType; cache_and_wrap_type('java.util.HashMap') end
121
+ def getRegexType; cache_and_wrap_type('java.util.regex.Pattern') end
122
+ def getStringType; cache_and_wrap_type('java.lang.String') end
123
+ def getBooleanType; cache_and_wrap_type('boolean') end
124
+
125
+ def getFixnumType(value)
126
+ long = java.lang.Long.new(value)
127
+ if long.int_value != value
128
+ cache_and_wrap_type('long')
129
+ elsif long.short_value != value
130
+ cache_and_wrap_type('int')
131
+ elsif long.byte_value != value
132
+ wide = type(nil, 'int')
133
+ narrow = type(nil, 'short')
134
+ NarrowingTypeFuture.new(nil, wide, narrow)
135
+ else
136
+ wide = type(nil, 'int')
137
+ narrow = type(nil, 'byte')
138
+ NarrowingTypeFuture.new(nil, wide, narrow)
139
+ end
140
+ end
141
+
142
+ def getCharType(value) cache_and_wrap_type('char') end
143
+
144
+ def getFloatType(value)
145
+ d = java.lang.Double.new(value)
146
+ if d.float_value != value
147
+ cache_and_wrap_type('double')
148
+ else
149
+ wide = type(nil, 'double')
150
+ narrow = type(nil, 'float')
151
+ NarrowingTypeFuture.new(nil, wide, narrow)
152
+ end
153
+ end
154
+
155
+ def getMetaType(type)
156
+ if type.kind_of?(Type)
157
+ type.meta
158
+ else
159
+ future = BaseTypeFuture.new(nil)
160
+ type.on_update {|_, resolved| future.resolved(resolved.meta)}
161
+ future.position_set(type.position)
162
+ future.error_message_set(type.error_message)
163
+ future
164
+ end
165
+ end
166
+
167
+ def getSuperClass(future)
168
+ superclass = BaseTypeFuture.new(nil)
169
+ future.on_update do |_, type|
170
+ superclass.resolved(type.superclass)
171
+ end
172
+ superclass
173
+ end
174
+
175
+ def getArrayType(type)
176
+ if type.kind_of?(Type)
177
+ type.array_type
178
+ else
179
+ future = BaseTypeFuture.new(nil)
180
+ type.on_update {|_, resolved| future.resolved(resolved.array_type)}
181
+ future
182
+ end
183
+ end
184
+
185
+ def box(type)
186
+ boxed = BaseTypeFuture.new(nil)
187
+ type.on_update do |_, resolved|
188
+ if resolved.isError || !resolved.primitive?
189
+ boxed.resolved(resolved)
190
+ else
191
+ boxed.resolved(resolved.box_type)
192
+ end
193
+ end
194
+ boxed
195
+ end
196
+
197
+ def getArrayLiteralType(type, position)
198
+ result = Mirah::JVM::Types::GenericType.new(type(nil, 'java.util.List')) # Upgrade to a generic type.
199
+ variable = result.type_parameters[0]
200
+ result.type_parameter_map[variable.name] = _build_generic_type_future(variable.bounds, position)
201
+ result.type_parameter_map[variable.name].assign(box(type), position)
202
+ wrap(result)
203
+ rescue => ex
204
+ Mirah.print_error("Error inferring generics: #{ex.message}", position)
205
+ log("Error inferring generics: #{ex.message}\n#{ex.backtrace.join("\n")}")
206
+ cache_and_wrap_type('java.util.List')
207
+ end
208
+
209
+ def getHashLiteralType(key_type, value_type, position)
210
+ result = Mirah::JVM::Types::GenericType.new(type(nil, 'java.util.HashMap')) # Upgrade to a generic type.
211
+ generic_key, generic_value = result.type_parameters
212
+ for variable, type in [[generic_key, key_type], [generic_value, value_type]]
213
+ result.type_parameter_map[variable.name] = _build_generic_type_future(variable.bounds, position)
214
+ result.type_parameter_map[variable.name].assign(box(type), position)
215
+ end
216
+ wrap(result)
217
+ rescue => ex
218
+ Mirah.print_error("Error inferring generics: #{ex.message}", position)
219
+ log("Error inferring generics: #{ex.message}\n#{ex.backtrace.join("\n")}")
220
+ cache_and_wrap_type('java.util.HashMap')
221
+ end
222
+
223
+ def get(scope, typeref)
224
+ basic_type = if scope.nil?
225
+ cache_and_wrap_type(typeref.name)
226
+ else
227
+ imports = scope.imports
228
+ name = typeref.name
229
+ name = imports[name] while imports.include?(name)
230
+ types = [ cache_and_wrap_type(name), nil ]
231
+ packages = []
232
+ packages << scope.package if scope.package && scope.package != ''
233
+ (packages + scope.search_packages).each do |package|
234
+ types << cache_and_wrap_type("#{package}.#{name}")
235
+ types << nil
236
+ end
237
+
238
+ future = PickFirst.new(types, nil)
239
+ future.position_set(typeref.position)
240
+ future.error_message_set("Cannot find class #{typeref.name}")
241
+ future
242
+ end
243
+ if typeref.isArray
244
+ getArrayType(basic_type)
245
+ elsif typeref.isStatic
246
+ getMetaType(basic_type)
247
+ else
248
+ basic_type
249
+ end
250
+ end
251
+
252
+ def getLocalType(scope, name, position)
253
+ scope.local_type(name, position)
254
+ end
255
+
256
+ def getMethodType(call)
257
+ target = call.resolved_target
258
+ argTypes = call.resolved_parameters
259
+ macro_types = call.parameter_nodes.map do |node|
260
+ get_type(node.java_class.name)
261
+ end if call.parameter_nodes
262
+ _find_method_type(call.scope, target, call.name, argTypes, macro_types, call.position)
263
+ rescue => ex
264
+ Mirah.print_error("Error getting method type #{target.name}.#{call.name}: #{ex.message}", call.position)
265
+ puts ex.backtrace.join("\n\t")
266
+ ErrorType.new([["Internal error: #{ex}", call.position]])
267
+ end
268
+
269
+ def _find_method_type(scope, target, name, argTypes, macroTypes, position)
270
+ if target.respond_to?(:isError) && target.isError
271
+ return target
272
+ end
273
+ type = BaseTypeFuture.new(nil)
274
+ target.find_method2(target, name, argTypes, macroTypes, target.meta?, scope) do |method|
275
+ if method.nil?
276
+ unless argTypes.any?{|t| t && t.isError && (type.resolved(t); true)}
277
+ type.resolved(ErrorType.new([
278
+ ["Cannot find %s method %s(%s) on %s" %
279
+ [ target.meta? ? "static" : "instance",
280
+ name,
281
+ argTypes.map{|t| t ? t.full_name : "?"}.join(', '),
282
+ target.full_name], position]]))
283
+ end
284
+ elsif method.kind_of?(Exception)
285
+ type.resolved(ErrorType.new([[method.message, position]]))
286
+ else
287
+ result = method.return_type
288
+
289
+ # Handle generics.
290
+ begin
291
+ if name == 'new' and target.type_parameters
292
+ result = Mirah::JVM::Types::GenericType.new(result) # Upgrade to a generic type.
293
+ target.type_parameters.each do |var|
294
+ result.type_parameter_map.put(var.name, _build_generic_type_future(var.bounds, position))
295
+ end
296
+
297
+ genericParameterTypes = method.member.generic_parameter_types
298
+ if genericParameterTypes
299
+ genericParameterTypes.each_index do |i|
300
+ _handle_nested_generic_parameter(genericParameterTypes[i], argTypes[i], result.type_parameter_map, position)
301
+ end
302
+ end
303
+ elsif target.generic? && method.respond_to?(:member)
304
+ genericParameterTypes = method.member.generic_parameter_types
305
+ if genericParameterTypes
306
+ genericParameterTypes.each_index do |i|
307
+ _handle_nested_generic_parameter(genericParameterTypes[i], argTypes[i], target.type_parameter_map, position)
308
+ end
309
+ end
310
+
311
+ result = _handle_nested_generic_return(result, method.member.generic_return_type, target.type_parameter_map, position)
312
+ result.resolve if result.respond_to?(:resolve)
313
+ end
314
+ rescue => ex
315
+ Mirah.print_error("Error inferring generics: #{ex.message}", position)
316
+ log("Error inferring generics: #{ex.message}\n#{ex.backtrace.join("\n")}")
317
+ result = method.return_type
318
+ end
319
+
320
+ if result.kind_of?(TypeFuture)
321
+ if result.isResolved
322
+ type.resolved(result.resolve)
323
+ else
324
+ result.onUpdate {|x, resolved| type.resolved(resolved) }
325
+ end
326
+ else
327
+ type.resolved(result)
328
+ end
329
+
330
+ # TODO(shepheb): This is modifying the argTypes of _find_method_type, and it shouldn't be.
331
+ # Moved to the bottom so the generics code above can access the original argTypes that were passed to _find_method_type.
332
+ argTypes = method.argument_types
333
+ end
334
+ end
335
+ argTypes = argTypes.map do |t|
336
+ if t.nil?
337
+ t
338
+ elsif t.isBlock
339
+ type.position_set(position) if (position && type.position.nil?)
340
+ # This should only happen if type is an error.
341
+ type.resolve
342
+ else
343
+ t
344
+ end
345
+ end
346
+ return_type = AssignableTypeFuture.new(nil)
347
+ return_type.assign(type, position)
348
+ MethodFuture.new(name, argTypes, return_type, false, position)
349
+ end
350
+
351
+ def _build_generic_type_future(bounds, position)
352
+ typeName = "java.lang.Object"
353
+ if bounds.size > 1
354
+ raise ArgumentError, "Multiple bounds on type variables are not supported."
355
+ elsif bounds.size == 1
356
+ typeName = bounds[0].raw_type.getClassName
357
+ end
358
+ GenericTypeFuture.new(position, type(nil, typeName))
359
+ end
360
+
361
+ def _handle_nested_generic_parameter(expectedType, providedType, type_parameter_map, position)
362
+ if expectedType.kind_of?(BiteScript::ASM::TypeVariable)
363
+ gtf = type_parameter_map.get(expectedType.name)
364
+ gtf.assign(SimpleFuture.new(providedType), position)
365
+ elsif expectedType.kind_of?(BiteScript::ASM::Wildcard) && providedType.kind_of?(TypeFuture)
366
+ # TODO(shepheb): Handle bounds here.
367
+ gtf = type_parameter_map.get(expectedType.upper_bound.name)
368
+ gtf.assign(providedType, position)
369
+ elsif expectedType.kind_of?(BiteScript::ASM::ParameterizedType)
370
+ # We can assume assignable_from? here, or this method would not have been called.
371
+ expectedParameters = expectedType.type_arguments
372
+ # Look up the values of the provided type's parameters.
373
+ providedParameters = providedType.type_parameters.map do |var|
374
+ if providedType.generic?
375
+ providedType.type_parameter_map.get(var.name)
376
+ else
377
+ type_parameter_map.get(var.name)
378
+ end
379
+ end
380
+
381
+ if expectedParameters && providedParameters && expectedParameters.size == providedParameters.size
382
+ expectedParameters.each_index do |i|
383
+ _handle_nested_generic_parameter(expectedParameters[i], providedParameters[i], type_parameter_map, position)
384
+ end
385
+ else
386
+ raise ArgumentError, "Type parameter mismatch: Expected #{expectedParameters}, found #{providedParameters}."
387
+ end
388
+ end
389
+ end
390
+
391
+ # TODO(shepheb): Handles only one level of nesting, it should handle arbitrary depth by recursion.
392
+ def _handle_nested_generic_return(returnType, genericReturnType, type_parameter_map, position)
393
+ if genericReturnType.kind_of?(BiteScript::ASM::TypeVariable)
394
+ type_parameter_map.get(genericReturnType.name)
395
+ elsif genericReturnType.kind_of?(BiteScript::ASM::ParameterizedType)
396
+ returnType = GenericType.new(returnType)
397
+ expectedTypeParameters = returnType.jvm_type.type_parameters
398
+ providedTypeParameters = genericReturnType.type_arguments
399
+ if expectedTypeParameters && providedTypeParameters && expectedTypeParameters.size == providedTypeParameters.size
400
+ expectedTypeParameters.each_index do |i|
401
+ returnType.type_parameter_map.put(expectedTypeParameters[i].name, type_parameter_map.get(providedTypeParameters[i].name))
402
+ end
403
+ else
404
+ raise ArgumentError, "Type parameter mismatch: Expected #{expectedTypeParameters}, found #{providedTypeParameters}"
405
+ end
406
+ returnType
407
+ else
408
+ returnType
409
+ end
410
+ end
411
+
412
+ def getMethodDefType(target, name, argTypes, returnType, position)
413
+ if target.nil?
414
+ return ErrorType.new([["No target", position]])
415
+ end
416
+ unless argTypes.all? {|a| a.hasDeclaration}
417
+ infer_override_args(target, name, argTypes)
418
+ end
419
+ if returnType.nil?
420
+ returnType = infer_override_return_type(target, name, argTypes)
421
+ end
422
+
423
+ args = argTypes.map {|a| a.resolve}
424
+ target = target.resolve
425
+ type = _find_method_type(nil, target, name, args, nil, position)
426
+ type.onUpdate do |m, resolved|
427
+ _declare_method(target, name, args, type)
428
+ end
429
+
430
+ args.each_with_index do |arg, i|
431
+ if arg.isError
432
+ argTypes[i].onUpdate do |x, resolved|
433
+ args[i] = resolved
434
+ _declare_method(target, name, args, type)
435
+ end
436
+ end
437
+ end
438
+
439
+ if type.kind_of?(ErrorType)
440
+ puts "Got error type for method #{name} on #{target.resolve} (#{target.resolve.class})"
441
+ position = type.position rescue nil
442
+ return_type = AssignableTypeFuture.new(position)
443
+ return_type.declare(type, position)
444
+ type = MethodFuture.new(name, args, return_type, false, position)
445
+ elsif returnType
446
+ type.returnType.declare(returnType, position)
447
+ end
448
+
449
+ type.to_java(MethodFuture)
450
+ rescue => ex
451
+ target_name = target.respond_to?(:name) ? target.name : target.resolve.name
452
+ error("Error getting method def type #{target_name}.#{name}: #{ex.message}\n#{ex.backtrace.join("\n\t")}")
453
+ return_type = AssignableTypeFuture.new(nil)
454
+ return_type.declare(ErrorType.new([["Internal error: #{ex}"]]), nil)
455
+ MethodFuture.new(name, [], return_type, false, nil)
456
+ end
457
+
458
+ def _declare_method(target, name, args, type)
459
+ return if args.any? {|a| a.isError }
460
+ return unless type.kind_of?(MethodFuture) && type.returnType.isResolved
461
+ resolved = type.returnType.resolve
462
+ resolved = resolved.returnType if resolved.respond_to?(:returnType)
463
+ log "Learned {0} method {1}.{2}({3}) = {4}", [
464
+ target.meta? ? "static" : "instance",
465
+ target.full_name,
466
+ name,
467
+ args.map{|a| a.full_name}.join(', '),
468
+ resolved.full_name].to_java
469
+ rewritten_name = name.sub(/=$/, '_set')
470
+ if target.meta?
471
+ target.unmeta.declare_static_method(rewritten_name, args, resolved, [])
472
+ else
473
+ target.declare_method(rewritten_name, args, resolved, [])
474
+ end
475
+ end
476
+
477
+ def getMainType(scope, script)
478
+ filename = File.basename(script.position.source.name || 'DashE')
479
+ classname = Mirah::JVM::Compiler::JVMBytecode.classname_from_filename(filename)
480
+ getMetaType(cache_and_wrap(declare_type(scope, classname)))
481
+ end
482
+
483
+ def defineType(scope, node, name, superclass, interfaces)
484
+ # TODO what if superclass or interfaces change later?
485
+ log("Defining type #{name} < #{superclass.resolve.name if superclass} #{interfaces.map{|i|i.resolve.name}.inspect}")
486
+ type = define_type(scope, node)
487
+ future = @futures[type.name]
488
+ if future
489
+ future.resolved(type)
490
+ future
491
+ else
492
+ cache_and_wrap(type)
493
+ end
494
+ rescue => ex
495
+ Mirah.print_error("Error defining type #{name}: #{ex.message}", node.position)
496
+ puts ex.backtrace.join("\n\t")
497
+ ErrorType.new([["Internal error: #{ex}", node.position]])
498
+ end
499
+
500
+ def addMacro(klass, macro)
501
+ klass.unmeta.add_compiled_macro(macro)
502
+ end
503
+
504
+ def extendClass(classname, extensions)
505
+ get_type(classname).load_extensions(extensions)
506
+ end
507
+
508
+ def infer_override_args(target, name, arg_types)
509
+ # TODO What if the method we're overriding hasn't been inferred yet?
510
+ log("Infering argument types for #{name}")
511
+ by_name = target.resolve.find_callable_methods(name, true)
512
+ by_name_and_arity = by_name.select {|m| m.argument_types.size == arg_types.size}
513
+ filtered_args = Set.new(by_name_and_arity.map {|m| m.argument_types})
514
+ if filtered_args.size == 1
515
+ arg_types.zip(filtered_args.first).each do |arg, super_arg|
516
+ arg.declare(cache_and_wrap(super_arg), arg.position)
517
+ end
518
+ else
519
+ log("Found method types:")
520
+ filtered_args.each {|args| log(" #{args.map{|a|a.full_name}.inspect}")}
521
+ arg_types.each {|arg| arg.declare(ErrorType.new([["Missing declaration"]]), nil)}
522
+ # TODO else give a more useful error?
523
+ end
524
+ end
525
+
526
+ def infer_override_return_type(target, name, arg_types)
527
+ by_name = target.resolve.find_callable_methods(name, true)
528
+ by_name_and_arity = {}
529
+ by_name.each {|m| by_name_and_arity[m.argument_types] = m if m.argument_types.size == arg_types.size }
530
+ resolved_args = arg_types.map {|a| a.resolve}
531
+ match = by_name_and_arity[resolved_args]
532
+ return cache_and_wrap(match.return_type) if match
68
533
  end
69
534
 
70
535
  def define_types(builder)
@@ -80,10 +545,12 @@ module Mirah::JVM::Types
80
545
  else
81
546
  name = name.getClassName
82
547
  end
548
+ elsif name.kind_of?(Type) && name.array?
549
+ array = true
83
550
  end
84
551
  type = basic_type(scope, name)
85
- type = type.array_type if array
86
- type = type.meta if meta
552
+ type = type.array_type if type && array
553
+ type = type.meta if type && meta
87
554
  return type
88
555
  end
89
556
 
@@ -93,8 +560,9 @@ module Mirah::JVM::Types
93
560
  end
94
561
  orig = name
95
562
  if name.kind_of? Java::JavaClass
563
+ #TODO is is possible to get here anymore?
96
564
  if name.array?
97
- return type(name.component_type, true)
565
+ return type(scope, name.component_type, true)
98
566
  else
99
567
  name = name.name
100
568
  end
@@ -108,18 +576,15 @@ module Mirah::JVM::Types
108
576
  end
109
577
 
110
578
  def find_type(scope, name)
111
- saved_ex = nil
112
- begin
113
- return get_type(name)
114
- rescue NameError => ex
115
- saved_ex = ex
116
- end
579
+ type = get_type(name)
580
+ return type if type
117
581
 
118
582
  if scope
119
- imports = scope.static_scope.imports
583
+ imports = scope.imports
120
584
  if imports.include?(name)
121
585
  name = imports[name] while imports.include?(name)
122
- return get_type(name)
586
+ type = get_type(name)
587
+ return type if type
123
588
  end
124
589
 
125
590
  # TODO support inner class names
@@ -127,44 +592,44 @@ module Mirah::JVM::Types
127
592
  return package_search(name, scope)
128
593
  end
129
594
  end
130
- raise saved_ex
595
+ return nil
131
596
  end
132
597
 
133
598
  def package_search(name, scope)
134
599
  packages = []
135
- packages << scope.static_scope.package unless scope.static_scope.package.empty?
136
- packages.concat(scope.static_scope.search_packages)
600
+ current_package = scope.package
601
+ packages << current_package unless current_package.nil? || current_package.empty?
602
+ packages.concat(scope.search_packages)
137
603
  packages << 'java.lang'
138
604
  packages.each do |package|
139
- begin
140
- return get_type("#{package}.#{name}")
141
- rescue NameError
142
- end
605
+ type = get_type("#{package}.#{name}")
606
+ return type if type
143
607
  end
144
- raise NameError, "Cannot find class #{name}"
608
+ return nil
609
+ end
610
+
611
+ def getBlockType
612
+ @block_type ||= BlockType.new
145
613
  end
146
614
 
147
615
  def get_type(full_name)
148
616
  type = @known_types[full_name]
149
617
  return type.basic_type if type
150
- begin
151
- mirror = get_mirror(full_name)
152
- rescue NameError => ex
618
+ mirror = get_mirror(full_name)
619
+ unless mirror
153
620
  if full_name =~ /^(.+)\.([^.]+)/
154
621
  outer_name = $1
155
622
  inner_name = $2
156
- begin
157
- outer_type = get_type(outer_name)
158
- full_name = "#{outer_type.name}$#{inner_name}"
159
- rescue NameError
160
- raise ex
161
- end
623
+ outer_type = get_type(outer_name)
624
+ return nil if outer_type.nil?
625
+ full_name = "#{outer_type.name}$#{inner_name}"
162
626
  mirror = get_mirror(full_name)
627
+ return nil if mirror.nil?
163
628
  else
164
- raise ex
629
+ return nil
165
630
  end
166
631
  end
167
- type = Type.new(mirror).load_extensions
632
+ type = Type.new(self, mirror).load_extensions
168
633
  if full_name.include? '$'
169
634
  @known_types[full_name.gsub('$', '.')] = type
170
635
  end
@@ -172,83 +637,105 @@ module Mirah::JVM::Types
172
637
  end
173
638
 
174
639
  def known_type(scope, name)
175
- basic_type(scope, name) rescue nil
640
+ basic_type(scope, name)
176
641
  end
177
642
 
178
643
  def declare_type(scope, name)
179
644
  full_name = name
180
- package = scope.static_scope.package
181
- if !name.include?('.') && !package.empty?
182
- full_name = "#{package}.#{name}"
645
+ package = scope.package
646
+ if !name.include?('.')
647
+ if package && !package.empty?
648
+ full_name = "#{package}.#{name}"
649
+ else
650
+ scope.on_package_change do
651
+ full_name = "#{scope.package}.#{name}"
652
+ scope.import(full_name, name)
653
+ @known_types[full_name] = @known_types[name]
654
+ end
655
+ end
183
656
  end
184
657
  if @known_types.include? full_name
185
658
  @known_types[full_name]
186
659
  else
187
- scope.static_scope.import(full_name, name)
188
- @known_types[full_name] = TypeDefinition.new(full_name, nil)
660
+ scope.import(full_name, name)
661
+ @known_types[full_name] = TypeDefinition.new(self, scope, full_name, nil)
189
662
  end
190
663
  end
191
664
 
192
- def define_type(node)
193
- name = node.name
665
+ def define_type(scope, node)
666
+ if node.name.nil?
667
+ outer_node = node.find_ancestor {|n| (n != node && n.kind_of?(ClassDefinition)) || n.kind_of?(Script)}
668
+ if outer_node.kind_of?(ClassDefinition)
669
+ outer_name = outer_node.name.identifier
670
+ else
671
+ outer_name = Mirah::JVM::Compiler::JVMBytecode.classname_from_filename(node.position.source.name || 'DashE')
672
+ end
673
+ id = (@anonymous_classes[outer_name] += 1)
674
+ node.name_set(SimpleString.new("#{outer_name}$#{id}"))
675
+ end
676
+ name = node.name.identifier
194
677
  full_name = name
195
- package = node.static_scope.package
196
- if !name.include?('.') && !package.empty?
678
+ package = scope.package
679
+ if !name.include?('.') && package && !package.empty?
197
680
  full_name = "#{package}.#{name}"
198
681
  end
199
- if @known_types.include? full_name
682
+ if @known_types.include?(full_name) && @known_types[full_name].kind_of?(TypeDefinition)
200
683
  existing = @known_types[full_name]
201
- existing.node ||= node
684
+ unless existing.node
685
+ existing.node = node
686
+ existing.scope = scope
687
+ end
202
688
  existing
203
689
  else
204
- if Mirah::AST::InterfaceDeclaration === node
690
+ if InterfaceDeclaration === node
205
691
  klass = InterfaceDefinition
206
692
  else
207
693
  klass = TypeDefinition
208
694
  end
209
- node.scope.static_scope.import(full_name, name)
210
- @known_types[full_name] = klass.new(full_name, node)
695
+ scope.import(full_name, name)
696
+ @known_types[full_name] = klass.new(self, scope, full_name, node)
211
697
  end
212
698
  end
213
699
 
214
- def no_type
215
- Void
216
- end
217
-
218
- def unreachable_type
219
- Unreachable
220
- end
221
-
222
700
  def make_urls(classpath)
223
701
  Mirah::Env.decode_paths(classpath).map do |filename|
224
702
  java.io.File.new(filename).to_uri.to_url
225
703
  end.to_java(java.net.URL)
226
704
  end
227
705
 
706
+ def base_classpath
707
+ Mirah::Env.encode_paths(['.',
708
+ File.dirname(__FILE__) + '/../../../../javalib/mirah-builtins.jar',
709
+ File.dirname(__FILE__) + '/../../../../javalib/mirah-parser.jar',
710
+ File.dirname(__FILE__) + '/../../../../javalib/mirah-bootstrap.jar'])
711
+ end
712
+
228
713
  def classpath
229
- @classpath ||= '.'
714
+ @classpath ||= base_classpath
230
715
  end
231
716
 
232
717
  def classpath=(classpath)
233
- @classpath = classpath
718
+ if classpath
719
+ @classpath = classpath + ":" + base_classpath
720
+ end
234
721
  @resource_loader = nil
235
722
  end
236
-
723
+
237
724
  def resource_loader
238
725
  @resource_loader ||= URLClassLoader.new(make_urls(classpath), bootstrap_loader)
239
726
  end
240
-
727
+
241
728
  def bootstrap_loader
242
729
  @bootstrap_loader ||= begin
243
730
  parent = if bootclasspath
244
731
  Mirah::Util::IsolatedResourceLoader.new(make_urls(bootclasspath))
245
732
  end
246
- bootstrap_path = if __FILE__.match /file:.*\.jar!.*/
247
- File.expand_path(__FILE__).sub(/!.*$/,'').sub('file:','')
248
- else
249
- File.expand_path("#{__FILE__}/../../../../../javalib/mirah-bootstrap.jar")
250
- end
251
- bootstrap_urls = [java.io.File.new(bootstrap_path).to_uri.to_url].to_java(java.net.URL)
733
+ if __FILE__ =~ /^(file:.+jar)!/
734
+ bootstrap_urls = [java.net.URL.new($1)].to_java(java.net.URL)
735
+ else
736
+ bootstrap_jar = File.expand_path("#{__FILE__}/../../../../../javalib/mirah-bootstrap.jar")
737
+ bootstrap_urls = [java.io.File.new(bootstrap_jar).to_uri.to_url].to_java(java.net.URL)
738
+ end
252
739
  URLClassLoader.new(bootstrap_urls, parent)
253
740
  end
254
741
  end
@@ -258,15 +745,28 @@ module Mirah::JVM::Types
258
745
  @bootstrap_loader = nil
259
746
  @resource_loader = nil
260
747
  end
261
-
748
+
262
749
  attr_reader :bootclasspath
263
-
750
+
751
+ def mirror_class(klass)
752
+ name = klass.name.tr('.', '/')
753
+ if klass.respond_to?(:resource_as_stream)
754
+ stream = klass.resource_as_stream("/#{name}.class")
755
+ elsif klass.respond_to?(:get_resource_as_stream)
756
+ stream = klass.get_resource_as_stream("/#{name}.class")
757
+ else
758
+ return get_mirror(klass.name)
759
+ end
760
+ BiteScript::ASM::ClassMirror.load(stream)
761
+ end
762
+
264
763
  def get_mirror(name)
265
764
  @mirrors[name] ||= begin
266
765
  classname = name.tr('.', '/')
267
766
  stream = resource_loader.getResourceAsStream(classname + ".class")
268
767
  if stream
269
- BiteScript::ASM::ClassMirror.load(stream) if stream
768
+ mirror = BiteScript::ASM::ClassMirror.load(stream)
769
+ mirror if mirror.type.class_name == name
270
770
  else
271
771
  # TODO(ribrdb) Should this use a separate sourcepath?
272
772
  url = resource_loader.getResource(classname + ".java")
@@ -277,11 +777,41 @@ module Mirah::JVM::Types
277
777
  @mirrors[mirror.type.class_name] = mirror
278
778
  end if mirrors
279
779
  @mirrors[name]
280
- else
281
- raise NameError, "Class '#{name}' not found."
282
780
  end
283
781
  end
284
782
  end
285
783
  end
784
+
785
+ def getAbstractMethods(type)
786
+ methods = []
787
+ unless type.isError
788
+ object = get_type("java.lang.Object")
789
+ interfaces = [type]
790
+ until interfaces.empty?
791
+ interface = interfaces.pop
792
+ abstract_methods = interface.declared_instance_methods.select {|m| m.abstract?}
793
+ methods += abstract_methods.select do |m|
794
+ begin
795
+ # Skip methods defined on Object
796
+ object.java_method(m.name, *m.argument_types)
797
+ false
798
+ rescue NameError
799
+ true
800
+ end
801
+ end
802
+ interfaces.concat(interface.interfaces)
803
+ end
804
+ # TODO ensure this works with hierarchies of abstract classes
805
+ # reject the methods implemented by the abstract class
806
+ if type.abstract?
807
+ implemented_methods = type.declared_instance_methods.reject{|m| m.abstract?}.map { |m| [m.name, m.argument_types, m.return_type] }
808
+ methods = methods.reject{|m| implemented_methods.include? [m.name, m.argument_types, m.return_type] }
809
+ end
810
+ end
811
+ methods.map do |method|
812
+ MethodType.new(method.name, method.argument_types, method.return_type, false)
813
+ end
814
+ end
286
815
  end
287
816
  end
817
+ require 'mirah/jvm/types/basic_types'