mirah 0.0.12-java → 0.1.0-java

Sign up to get free protection for your applications and to get access to all the features.
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'