mirah 0.1.0.pre-java → 0.1.1-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. data/History.txt +736 -0
  2. data/README.md +71 -0
  3. data/Rakefile +227 -73
  4. data/examples/Fib.class +0 -0
  5. data/examples/macros/{string-each-char.mirah → string_each_char.mirah} +2 -3
  6. data/examples/simple_class.mirah +3 -3
  7. data/examples/{dynamic.mirah → simple_class.mirah~} +7 -12
  8. data/javalib/mirah-bootstrap.jar +0 -0
  9. data/javalib/mirah-builtins.jar +0 -0
  10. data/javalib/mirah-compiler.jar +0 -0
  11. data/javalib/mirah-parser.jar +0 -0
  12. data/javalib/mirah-util.jar +0 -0
  13. data/lib/mirah.rb +8 -1
  14. data/lib/mirah/ast.rb +1 -1
  15. data/lib/mirah/ast/scope.rb +16 -0
  16. data/lib/mirah/commands/base.rb +1 -3
  17. data/lib/mirah/compiler.rb +17 -3
  18. data/lib/mirah/errors.rb +10 -10
  19. data/lib/mirah/generator.rb +21 -9
  20. data/lib/mirah/jvm/compiler.rb +17 -0
  21. data/lib/mirah/jvm/compiler/base.rb +24 -5
  22. data/lib/mirah/jvm/compiler/jvm_bytecode.rb +83 -20
  23. data/lib/mirah/jvm/method_lookup.rb +43 -22
  24. data/lib/mirah/jvm/types.rb +1 -2
  25. data/lib/mirah/jvm/types/array_type.rb +1 -6
  26. data/lib/mirah/jvm/types/ast_ext.rb +31 -0
  27. data/lib/mirah/jvm/types/basic_types.rb +1 -2
  28. data/lib/mirah/jvm/types/boolean.rb +11 -10
  29. data/lib/mirah/jvm/types/extensions.rb +14 -5
  30. data/lib/mirah/jvm/types/factory.rb +128 -43
  31. data/lib/mirah/jvm/types/floats.rb +8 -10
  32. data/lib/mirah/jvm/types/integers.rb +16 -9
  33. data/lib/mirah/jvm/types/intrinsics.rb +17 -69
  34. data/lib/mirah/jvm/types/meta_type.rb +5 -0
  35. data/lib/mirah/jvm/types/methods.rb +317 -151
  36. data/lib/mirah/jvm/types/methods.rb~ +973 -0
  37. data/lib/mirah/jvm/types/number.rb +29 -6
  38. data/lib/mirah/jvm/types/primitive_type.rb +35 -7
  39. data/lib/mirah/jvm/types/source_mirror.rb +11 -6
  40. data/lib/mirah/jvm/types/type.rb +52 -0
  41. data/lib/mirah/jvm/types/type_definition.rb +8 -2
  42. data/lib/mirah/transform/ast_ext.rb +9 -31
  43. data/lib/mirah/transform/transformer.rb +1 -1
  44. data/lib/mirah/typer.rb +2 -1
  45. data/lib/mirah/util/argument_processor.rb +10 -14
  46. data/lib/mirah/util/argument_processor.rb~ +146 -0
  47. data/lib/mirah/util/compilation_state.rb +15 -9
  48. data/lib/mirah/util/process_errors.rb +8 -2
  49. data/lib/mirah/version.rb +2 -2
  50. data/lib/mirah_task.rb +0 -7
  51. data/test/core/typer_test.rb +21 -13
  52. data/test/core/util/argument_processor_test.rb +19 -19
  53. data/test/core/util/class_loader_test.rb +19 -4
  54. data/test/core/util/compilation_state_test.rb +38 -0
  55. data/test/fixtures/org/foo/LowerCaseInnerClass$inner.class +0 -0
  56. data/test/fixtures/org/foo/LowerCaseInnerClass.class +0 -0
  57. data/test/fixtures/org/foo/LowerCaseInnerClass.java +7 -0
  58. data/test/jvm/blocks_test.rb +50 -29
  59. data/test/jvm/bytecode_test_helper.rb +71 -57
  60. data/test/jvm/cast_test.rb +162 -0
  61. data/test/jvm/constructors_test.rb +48 -0
  62. data/test/jvm/enumerable_test.rb +136 -7
  63. data/test/jvm/example_test.rb +39 -0
  64. data/test/jvm/factory_test.rb +6 -0
  65. data/test/jvm/generics_test.rb +0 -5
  66. data/test/jvm/import_test.rb +81 -0
  67. data/test/jvm/interface_test.rb +113 -0
  68. data/test/jvm/java_typer_test.rb +57 -11
  69. data/test/jvm/jvm_commands_test.rb +24 -0
  70. data/test/jvm/jvm_compiler_test.rb +186 -370
  71. data/test/jvm/macros_test.rb +67 -6
  72. data/test/jvm/main_method_test.rb +1 -1
  73. data/test/jvm/mirror_compilation_test_helper.rb +24 -0
  74. data/test/jvm/new_backend_test_helper.rb +25 -0
  75. data/test/jvm/rescue_test.rb +153 -18
  76. data/test/jvm/string_test.rb +41 -0
  77. data/test/jvm/varargs_test.rb +65 -0
  78. data/test/mirrors/base_type_test.rb +96 -0
  79. data/test/mirrors/bytecode_mirror_test.rb +86 -0
  80. data/test/mirrors/generics_test.rb +776 -0
  81. data/test/mirrors/member_test.rb +69 -0
  82. data/test/mirrors/method_lookup_test.rb +574 -0
  83. data/test/mirrors/mirrors_test.rb +562 -0
  84. data/test/mirrors/simple_async_mirror_loader_test.rb +110 -0
  85. data/test/mirrors/simple_mirror_loader_test.rb +104 -0
  86. data/test/test_helper.rb +2 -1
  87. metadata +244 -217
  88. data/README.txt +0 -59
  89. data/javalib/dynalink-0.2.jar +0 -0
  90. data/lib/mirah/jvm/typer.rb +0 -177
  91. data/lib/mirah/jvm/types/dynamic_type.rb +0 -45
  92. data/lib/mirah/jvm/types/unreachable_type.rb +0 -27
Binary file
@@ -14,10 +14,9 @@
14
14
  # limitations under the License.
15
15
 
16
16
 
17
- macro def eachChar(value, &block)
18
-
17
+ macro def eachChar(value, block:Block)
19
18
  quote {
20
- `value`.toCharArray.each do | my_char |
19
+ `value`.toCharArray.each do |`block.arguments` |
21
20
  `block.body`
22
21
  end
23
22
  }
@@ -13,15 +13,15 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- class Foo
16
+ class SimpleClass
17
17
  def initialize
18
18
  puts 'constructor'
19
19
  @hello = 'Hello, '
20
20
  end
21
21
 
22
- def hello(a:string)
22
+ def hello(a:String)
23
23
  puts @hello; puts a
24
24
  end
25
25
  end
26
26
 
27
- Foo.new.hello('Mirah')
27
+ SimpleClass.new.hello('Mirah')
@@ -13,20 +13,15 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- # Example of using a dynamic type in a method definition
17
- def foo(a:dynamic)
18
- puts "I got a #{a.getClass.getName} of size #{a.size}"
19
- end
20
-
21
- class SizeThing
22
- def initialize(size:int)
23
- @size = size
16
+ class Foo
17
+ def initialize
18
+ puts 'constructor'
19
+ @hello = 'Hello, '
24
20
  end
25
21
 
26
- def size
27
- @size
22
+ def hello(a:string)
23
+ puts @hello; puts a
28
24
  end
29
25
  end
30
26
 
31
- foo([1,2,3])
32
- foo(SizeThing.new(12))
27
+ Foo.new.hello('Mirah')
Binary file
Binary file
Binary file
Binary file
Binary file
data/lib/mirah.rb CHANGED
@@ -17,6 +17,13 @@ require 'fileutils'
17
17
  require 'rbconfig'
18
18
  require 'bitescript'
19
19
 
20
+ $CLASSPATH << File.dirname(__FILE__) + '/../javalib/mirah-builtins.jar'
21
+ $CLASSPATH << File.dirname(__FILE__) + '/../javalib/mirah-parser.jar'
22
+ $CLASSPATH << File.dirname(__FILE__) + '/../javalib/mirah-bootstrap.jar'
23
+ $CLASSPATH << File.dirname(__FILE__) + '/../javalib/mirah-util.jar'
24
+ $CLASSPATH << File.dirname(__FILE__) + '/../javalib/mirah-compiler.jar'
25
+ $CLASSPATH << File.dirname(__FILE__) + '/../javalib/mirah-mirrors.jar'
26
+
20
27
  require 'mirah/version'
21
28
  require 'mirah/transform'
22
29
  require 'mirah/ast'
@@ -78,7 +85,7 @@ module Mirah
78
85
  end_col -= adjustment
79
86
 
80
87
  result = ""
81
- position.source.contents.each_with_index do |line, lineno|
88
+ position.source.contents.each_line.with_index do |line, lineno|
82
89
  break if lineno > end_line
83
90
  next if lineno < start_line
84
91
 
data/lib/mirah/ast.rb CHANGED
@@ -34,10 +34,10 @@ module Mirah
34
34
  java_import 'mirah.lang.ast.NodeList'
35
35
  java_import 'mirah.lang.ast.Noop'
36
36
  java_import 'mirah.lang.ast.OptionalArgument'
37
+ java_import 'mirah.lang.ast.Position'
37
38
  java_import 'mirah.lang.ast.SimpleString'
38
39
  java_import 'mirah.lang.ast.TypeName'
39
40
  java_import 'mirah.lang.ast.TypeRef'
40
41
 
41
-
42
42
  end
43
43
  end
@@ -19,6 +19,7 @@ module Mirah
19
19
  java_import 'java.util.LinkedHashMap'
20
20
  java_import 'org.mirah.typer.Scope'
21
21
  java_import 'org.mirah.typer.AssignableTypeFuture'
22
+ java_import 'org.mirah.typer.BaseTypeFuture'
22
23
  java_import 'org.mirah.typer.LocalFuture'
23
24
  java_import 'org.mirah.typer.ErrorType'
24
25
  include Scope
@@ -85,6 +86,10 @@ module Mirah
85
86
  def locals
86
87
  @vars.keys
87
88
  end
89
+
90
+ def capturedLocals
91
+ locals.select {|name| self.captured?(name)}
92
+ end
88
93
 
89
94
  def temp(name="tmp")
90
95
  "$#{name}$#{@temps[name] += 1}"
@@ -117,6 +122,10 @@ module Mirah
117
122
  end
118
123
  end
119
124
 
125
+ def isCaptured(name)
126
+ self.captured?(name)
127
+ end
128
+
120
129
  def children
121
130
  @children.keys
122
131
  end
@@ -214,6 +223,13 @@ module Mirah
214
223
  @cached_packages ||= fetch_packages([])
215
224
  end
216
225
 
226
+ def staticImport(type)
227
+ future = BaseTypeFuture.new(self_type.position)
228
+ extended = self_type.resolve.include(type.resolve)
229
+ future.resolved(extended)
230
+ self.self_type = future
231
+ end
232
+
217
233
  def import(full_name, short_name)
218
234
  return if full_name == short_name
219
235
  if short_name == '*'
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2010 The Mirah project authors. All Rights Reserved.
1
+ # Copyright (c) 2010-2013 The Mirah project authors. All Rights Reserved.
2
2
  # All contributing project authors may be found in the NOTICE file.
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -13,7 +13,6 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- #require 'mirah/jvm/types'
17
16
  require 'mirah/util/compilation_state'
18
17
  require 'mirah/util/argument_processor'
19
18
  require 'mirah/errors'
@@ -23,7 +22,6 @@ module Mirah
23
22
  class Base
24
23
  include Mirah::Logging::Logged
25
24
  def initialize(args)
26
- #Mirah::AST.type_factory = Mirah::JVM::Types::TypeFactory.new
27
25
  @state = Mirah::Util::CompilationState.new
28
26
  @state.command = command_name
29
27
  @args = args
@@ -16,7 +16,8 @@
16
16
  module Mirah
17
17
  module Compiler
18
18
  class ASTCompiler
19
- def initialize(compiler_class, logging)
19
+ def initialize(config, compiler_class, logging)
20
+ @config = config
20
21
  @compiler_class = compiler_class
21
22
  @logging = logging
22
23
  end
@@ -29,16 +30,29 @@ module Mirah
29
30
  nodes.each do |ast|
30
31
  puts " #{ast.position.source.name}" if logging
31
32
  compile_ast(ast, scoper, typer) do |filename, builder|
32
- results << CompilerResult.new(filename, builder.class_name, builder.generate)
33
+ if builder.respond_to?(:class_name)
34
+ class_name = builder.class_name
35
+ bytes = builder.generate
36
+ else
37
+ class_name = filename
38
+ bytes = String.from_java_bytes(builder)
39
+ filename = class_name.tr('.', '/') + ".class"
40
+ end
41
+ results << CompilerResult.new(filename, class_name, bytes)
33
42
  end
34
43
  end
35
44
  results
36
45
  end
37
46
 
38
47
  def compile_ast(ast, scoper, typer, &block)
39
- @compiler = compiler_class.new(scoper, typer)
48
+ @compiler = compiler_class.new(@config, scoper, typer)
40
49
  compiler.visit(ast, nil)
41
50
  compiler.generate(&block)
51
+ rescue java.lang.UnsupportedOperationException => ex
52
+ raise MirahError.new(ex.message)
53
+ rescue java.lang.Throwable => ex
54
+ ex.cause.printStackTrace if ex.cause
55
+ raise ex
42
56
  end
43
57
  end
44
58
 
data/lib/mirah/errors.rb CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2010 The Mirah project authors. All Rights Reserved.
1
+ # Copyright (c) 2010-2013 The Mirah project authors. All Rights Reserved.
2
2
  # All contributing project authors may be found in the NOTICE file.
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -34,23 +34,24 @@ module Mirah
34
34
  end
35
35
 
36
36
  def node=(node)
37
- @position = node ? node.position : nil
38
- @node = node
37
+ @position = node.position if node
38
+ @node = node
39
39
  end
40
40
 
41
41
  def self.wrap(ex, node)
42
- if ex.kind_of?(NodeError)
42
+ case ex
43
+ when NodeError
43
44
  ex.node ||= node
44
- return ex
45
- elsif ex.kind_of?(MirahError)
45
+ ex
46
+ when MirahError
46
47
  ex.position ||= node.position
47
- return ex
48
+ ex
48
49
  else
49
50
  new_ex = new(ex.message, node)
50
- new_ex.cause = ex
51
+ new_ex.cause = ex
51
52
  new_ex.position ||= ex.position if ex.respond_to?(:position)
52
53
  new_ex.set_backtrace(ex.backtrace)
53
- return new_ex
54
+ new_ex
54
55
  end
55
56
  end
56
57
 
@@ -66,7 +67,6 @@ module Mirah
66
67
  class SyntaxError < NodeError
67
68
  end
68
69
 
69
-
70
70
  class InferenceError < NodeError
71
71
  end
72
72
 
@@ -25,18 +25,30 @@ module Mirah
25
25
 
26
26
  def initialize(state, compiler_class, logging, verbose)
27
27
  @state = state
28
- @scoper = SimpleScoper.new {|scoper, node| Mirah::AST::StaticScope.new(node, scoper)}
29
28
 
30
29
  # TODO untie this from the jvm backend (nh)
31
- type_system = Mirah::JVM::Types::TypeFactory.new
32
- type_system.classpath = state.classpath
33
- type_system.bootclasspath = state.bootclasspath
30
+ if state.type_system
31
+ # Using new type system
32
+ @scoper = SimpleScoper.new do |scoper, node|
33
+ scope = Java::OrgMirahJvmMirrors::JVMScope.new(scoper)
34
+ scope.context_set(node)
35
+ scope
36
+ end
37
+ type_system = state.type_system
38
+ else
39
+ @scoper = SimpleScoper.new {|scoper, node| Mirah::AST::StaticScope.new(node, scoper)}
40
+ type_system = Mirah::JVM::Types::TypeFactory.new
41
+ type_system.classpath = state.classpath if state.classpath
42
+ type_system.bootclasspath = state.bootclasspath
43
+ end
34
44
 
35
- @typer = Mirah::Typer::Typer.new(type_system, @scoper, self)
45
+ @typer = Mirah::Typer::Typer.new(type_system, @scoper, self, nil)
36
46
  @parser = Mirah::Parser.new(state, @typer, logging)
37
- @compiler = Mirah::Compiler::ASTCompiler.new(compiler_class, logging)
38
- @jvm_compiler = Mirah::Compiler::ASTCompiler.new(Mirah::JVM::Compiler::JVMBytecode, logging)
39
- type_system.maybe_initialize_builtins(@typer.macro_compiler)
47
+ @compiler = Mirah::Compiler::ASTCompiler.new(state, compiler_class, logging)
48
+ @extension_compiler = Mirah::Compiler::ASTCompiler.new(state, compiler_class, logging)
49
+ if type_system.respond_to?(:maybe_initialize_builtins)
50
+ type_system.maybe_initialize_builtins(@typer.macro_compiler)
51
+ end
40
52
  @logging = logging
41
53
  @verbose = verbose
42
54
  end
@@ -93,7 +105,7 @@ module Mirah
93
105
  def compileAndLoadExtension(ast)
94
106
  log_types([ast])
95
107
  process_inference_errors(@typer, [ast])
96
- results = @jvm_compiler.compile_asts([ast], @scoper, @typer)
108
+ results = @extension_compiler.compile_asts([ast], @scoper, @typer)
97
109
  class_map = {}
98
110
  first_class_name = nil
99
111
  results.each do |result|
@@ -19,6 +19,7 @@ require 'mirah/jvm/method_lookup'
19
19
  require 'mirah/jvm/types'
20
20
  require 'bitescript'
21
21
  require 'mirah/jvm/compiler/jvm_bytecode'
22
+ require 'mirah/transform/ast_ext'
22
23
 
23
24
  module Mirah
24
25
  module AST
@@ -31,3 +32,19 @@ module Mirah
31
32
  end
32
33
  end
33
34
  end
35
+
36
+ module Mirah
37
+ module JVM
38
+ module Compiler
39
+ begin
40
+ class Backend < Java::OrgMirahJvmCompiler::Backend
41
+ def initialize(config, scoper, typer)
42
+ super(typer)
43
+ end
44
+ end
45
+ rescue NameError
46
+ puts "Unable to load new Backend"
47
+ end
48
+ end
49
+ end
50
+ end
@@ -32,16 +32,25 @@ module Mirah
32
32
  "org.mirah.ruby.JVM.Compiler.Base"
33
33
  end
34
34
 
35
- def initialize(scoper, typer)
35
+ def initialize(config, scoper, typer)
36
36
  super()
37
+ @config = config
37
38
  @jump_scope = []
38
39
  @bindings = Hash.new {|h, type| h[type] = type.define(@file)}
39
40
  @captured_locals = Hash.new {|h, binding| h[binding] = {}}
40
41
  @self_scope = nil
41
- @scoper = scoper
42
+ @scoper = typer.scoper
42
43
  @typer = typer
43
44
  end
44
45
 
46
+ def target_jvm_version
47
+ @config.target_jvm_version
48
+ end
49
+
50
+ def supports_invokedynamic?
51
+ @config.supports_invokedynamic?
52
+ end
53
+
45
54
  def defaultNode(node, expression)
46
55
  raise ArgumentError, "Can't compile node #{node}"
47
56
  end
@@ -192,9 +201,12 @@ module Mirah
192
201
 
193
202
  # arg_types must be an Array
194
203
  def create_method_builder(name, node, static, exceptions, return_type, arg_types)
204
+ return_type = nil if return_type.name == ':unreachable'
195
205
  visibility = :public # TODO
196
- @class.build_method(name.to_s, visibility, static,
197
- exceptions, return_type, *arg_types)
206
+ flags = BiteScript::ASM::Opcodes::ACC_PUBLIC
207
+ flags |= BiteScript::ASM::Opcodes::ACC_STATIC if static
208
+ flags |= BiteScript::ASM::Opcodes::ACC_ABSTRACT if node.annotated_abstract?
209
+ @class.method(flags, name.to_s, [return_type, *arg_types], exceptions)
198
210
  end
199
211
 
200
212
  def base_define_method(node)
@@ -205,7 +217,7 @@ module Mirah
205
217
  name = "<clinit>"
206
218
  end
207
219
  arg_types = args.map { |arg| inferred_type(arg) }
208
- return_type = inferred_type(node)
220
+ return_type = inferred_type(node).return_type
209
221
  exceptions = [] # TODO
210
222
 
211
223
  with :static => is_static, :current_scope => introduced_scope(node) do
@@ -341,6 +353,13 @@ module Mirah
341
353
  inferred_type(node).literal(method, node.value)
342
354
  end
343
355
  end
356
+
357
+ def visitCharLiteral(node, expression)
358
+ if expression
359
+ inferred_type(node).literal(method, node.value)
360
+ end
361
+ end
362
+
344
363
  alias visitFloat visitFixnum
345
364
 
346
365
  def visitSelf(node, expression)
@@ -1,3 +1,5 @@
1
+ require 'mirah/jvm/types/ast_ext'
2
+
1
3
  module Mirah
2
4
  module JVM
3
5
  module Compiler
@@ -40,7 +42,7 @@ module Mirah
40
42
  end
41
43
  end
42
44
 
43
- def initialize(scoper, typer)
45
+ def initialize(config, scoper, typer)
44
46
  super
45
47
  @jump_scope = []
46
48
  end
@@ -52,8 +54,8 @@ module Mirah
52
54
  def file_builder(filename)
53
55
  builder = BiteScript::FileBuilder.new(filename)
54
56
  builder.to_widen do |_a, _b|
55
- a = @typer.type_system.get_type(_a)
56
- b = @typer.type_system.get_type(_b)
57
+ a = @typer.type_system.get_type(_a.tr('/', '.'))
58
+ b = @typer.type_system.get_type(_b.tr('/', '.'))
57
59
  a_ancestors = []
58
60
  while a
59
61
  a_ancestors << a.name
@@ -65,7 +67,13 @@ module Mirah
65
67
  b = b.superclass
66
68
  end
67
69
  intersection = (a_ancestors & b_ancestors)
68
- intersection[0].gsub('.', '/')
70
+ if intersection.size == 0
71
+ puts "#{_a} => #{a}, #{_b} => #{b}"
72
+ puts "#{a_ancestors.inspect} & #{b_ancestors.inspect} = []"
73
+ 'java/lang/Object'
74
+ else
75
+ intersection[0].gsub('.', '/')
76
+ end
69
77
  end
70
78
  @typer.type_system.define_types(builder)
71
79
  builder
@@ -139,12 +147,12 @@ module Mirah
139
147
  def visitMethodDefinition(node, expression)
140
148
  push_jump_scope(node) do
141
149
  base_define_method(node) do |method, arg_types|
142
- return if @class.interface?
150
+ return if @class.interface? || node.annotated_abstract?
143
151
  is_static = self.static || node.kind_of?(StaticMethodDefinition)
144
152
 
145
153
  log "Starting new #{is_static ? 'static ' : ''}method #{node.name.identifier}(#{arg_types})"
146
154
  args = visit(node.arguments, true)
147
- method_body(method, args, node, inferred_type(node))
155
+ method_body(method, args, node, inferred_type(node).returnType)
148
156
  log "Method #{node.name.identifier}(#{arg_types}) complete!"
149
157
  end
150
158
  end
@@ -233,17 +241,26 @@ module Mirah
233
241
 
234
242
  prepare_binding(node) do
235
243
  expression = return_type.name != 'void'
236
- visit(body, expression) if body
244
+ if body
245
+ if expression
246
+ body_type = inferred_type(body)
247
+ unless return_type.assignableFrom(body_type)
248
+ error("Invalid return type #{body_type.name}, expected #{return_type.name}", body)
249
+ end
250
+ end
251
+ visit(body, expression)
252
+ convert_value inferred_type(body), return_type if expression
253
+ end
237
254
  end
238
255
 
239
- return_type.return(@method)
256
+ return_type.return(@method) unless return_type.name == ':unreachable'
240
257
 
241
258
  @method.stop
242
259
  end
243
260
  end
244
261
 
245
262
  def visitClosureDefinition(class_def, expression)
246
- compiler = ClosureCompiler.new(@file, @type, self, @scoper, @typer)
263
+ compiler = ClosureCompiler.new(@config, @file, @type, self, @scoper, @typer)
247
264
  compiler.visitClassDefinition(class_def, expression)
248
265
  end
249
266
 
@@ -440,6 +457,18 @@ module Mirah
440
457
  end
441
458
  end
442
459
 
460
+ def visitVarargsArray type, parameters
461
+ @method.push_int parameters.size
462
+ @method.anewarray type.component_type
463
+ parameters.each.with_index do |value, i|
464
+ @method.dup
465
+ @method.push_int i
466
+ visit(value, true)
467
+ convert_value inferred_type(value), type.component_type
468
+ @method.aastore
469
+ end
470
+ end
471
+
443
472
  def visitFunctionalCall(fcall, expression)
444
473
  scope = get_scope(fcall)
445
474
  type = get_scope(fcall).self_type.resolve
@@ -562,6 +591,7 @@ module Mirah
562
591
 
563
592
  def annotate(builder, annotations)
564
593
  annotations.each do |annotation|
594
+ next if annotation.type.typeref.name.start_with?('org.mirah.jvm.')
565
595
  type = inferred_type(annotation)
566
596
  mirror = type.jvm_type
567
597
  if mirror.respond_to?(:getDeclaredAnnotation)
@@ -730,19 +760,29 @@ module Mirah
730
760
  declare_local(scope, name, type)
731
761
 
732
762
  visit(local.value, true)
763
+ convert_value inferred_type(local.value), type
733
764
 
734
765
  # if expression, dup the value we're assigning
735
- @method.dup if expression
766
+ if expression
767
+ dup_value type
768
+ end
769
+
736
770
  set_position(local.position)
737
771
  type.store(@method, @method.local(scoped_local_name(name, scope), type))
738
772
  end
739
773
 
740
774
  def captured_local_assign(node, expression)
741
- scope, name, type = containing_scope(node), node.name.identifier, inferred_type(node)
775
+ scope, name = containing_scope(node), node.name.identifier
776
+ type = get_scope(node).local_type(name).resolve
742
777
  captured_local_declare(scope, name, type)
743
778
  binding_reference
744
779
  visit(node.value, true)
745
- @method.dup_x2 if expression
780
+ convert_value(inferred_type(node.value), type)
781
+
782
+ # if expression, dup the value we're assigning
783
+ if expression
784
+ dup_x2_value type
785
+ end
746
786
  set_position(node.position)
747
787
  @method.putfield(scope.binding_type, name, type)
748
788
  end
@@ -906,9 +946,6 @@ module Mirah
906
946
  @method.invokeinterface java::util::List, "add", [@method.boolean, @method.object]
907
947
  @method.pop
908
948
  end
909
-
910
- # make it unmodifiable
911
- @method.invokestatic java::util::Collections, "unmodifiableList", [java::util::List, java::util::List]
912
949
  else
913
950
  # elements, as non-expressions
914
951
  # TODO: ensure they're all reference types!
@@ -997,7 +1034,7 @@ module Mirah
997
1034
 
998
1035
  def set_position(position)
999
1036
  # TODO support positions from multiple files
1000
- @method.line(position.start_line - 1) if @method && position
1037
+ @method.line(position.start_line) if @method && position
1001
1038
  end
1002
1039
 
1003
1040
  def print(print_node)
@@ -1034,10 +1071,14 @@ module Mirah
1034
1071
  start = @method.label.set!
1035
1072
  body_end = @method.label
1036
1073
  done = @method.label
1037
- visit(rescue_node.body, expression && rescue_node.else_clause.size == 0)
1074
+ no_else_clauses = rescue_node.else_clause.size == 0
1075
+
1076
+ visit(rescue_node.body, expression && no_else_clauses)
1038
1077
  body_end.set!
1039
- visit(rescue_node.else_clause, expression) if rescue_node.else_clause.size > 0
1078
+
1079
+ visit(rescue_node.else_clause, expression) unless no_else_clauses
1040
1080
  return if start.label.offset == body_end.label.offset
1081
+
1041
1082
  @method.goto(done)
1042
1083
  rescue_node.clauses.each do |clause|
1043
1084
  target = @method.label.set!
@@ -1092,9 +1133,31 @@ module Mirah
1092
1133
  end
1093
1134
  end
1094
1135
 
1136
+ private
1137
+
1138
+ def convert_value in_type, out_type
1139
+ in_type.compile_widen(@method, out_type) if in_type.name != ':unreachable' && in_type.primitive?
1140
+ end
1141
+
1142
+ def dup_value type
1143
+ if type.primitive? && type.wide?
1144
+ @method.dup2
1145
+ else
1146
+ @method.dup
1147
+ end
1148
+ end
1149
+
1150
+ def dup_x2_value type
1151
+ if type.primitive? && type.wide?
1152
+ @method.dup2_x2
1153
+ else
1154
+ @method.dup_x2
1155
+ end
1156
+ end
1157
+
1095
1158
  class ClosureCompiler < JVMBytecode
1096
- def initialize(file, type, parent, scoper, typer)
1097
- super(scoper, typer)
1159
+ def initialize(config, file, type, parent, scoper, typer)
1160
+ super(config, scoper, typer)
1098
1161
  @file = file
1099
1162
  @type = type
1100
1163
  @jump_scope = []