mirah 0.1.0.pre-java → 0.1.1-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. data/History.txt +736 -0
  2. data/README.md +71 -0
  3. data/Rakefile +227 -73
  4. data/examples/Fib.class +0 -0
  5. data/examples/macros/{string-each-char.mirah → string_each_char.mirah} +2 -3
  6. data/examples/simple_class.mirah +3 -3
  7. data/examples/{dynamic.mirah → simple_class.mirah~} +7 -12
  8. data/javalib/mirah-bootstrap.jar +0 -0
  9. data/javalib/mirah-builtins.jar +0 -0
  10. data/javalib/mirah-compiler.jar +0 -0
  11. data/javalib/mirah-parser.jar +0 -0
  12. data/javalib/mirah-util.jar +0 -0
  13. data/lib/mirah.rb +8 -1
  14. data/lib/mirah/ast.rb +1 -1
  15. data/lib/mirah/ast/scope.rb +16 -0
  16. data/lib/mirah/commands/base.rb +1 -3
  17. data/lib/mirah/compiler.rb +17 -3
  18. data/lib/mirah/errors.rb +10 -10
  19. data/lib/mirah/generator.rb +21 -9
  20. data/lib/mirah/jvm/compiler.rb +17 -0
  21. data/lib/mirah/jvm/compiler/base.rb +24 -5
  22. data/lib/mirah/jvm/compiler/jvm_bytecode.rb +83 -20
  23. data/lib/mirah/jvm/method_lookup.rb +43 -22
  24. data/lib/mirah/jvm/types.rb +1 -2
  25. data/lib/mirah/jvm/types/array_type.rb +1 -6
  26. data/lib/mirah/jvm/types/ast_ext.rb +31 -0
  27. data/lib/mirah/jvm/types/basic_types.rb +1 -2
  28. data/lib/mirah/jvm/types/boolean.rb +11 -10
  29. data/lib/mirah/jvm/types/extensions.rb +14 -5
  30. data/lib/mirah/jvm/types/factory.rb +128 -43
  31. data/lib/mirah/jvm/types/floats.rb +8 -10
  32. data/lib/mirah/jvm/types/integers.rb +16 -9
  33. data/lib/mirah/jvm/types/intrinsics.rb +17 -69
  34. data/lib/mirah/jvm/types/meta_type.rb +5 -0
  35. data/lib/mirah/jvm/types/methods.rb +317 -151
  36. data/lib/mirah/jvm/types/methods.rb~ +973 -0
  37. data/lib/mirah/jvm/types/number.rb +29 -6
  38. data/lib/mirah/jvm/types/primitive_type.rb +35 -7
  39. data/lib/mirah/jvm/types/source_mirror.rb +11 -6
  40. data/lib/mirah/jvm/types/type.rb +52 -0
  41. data/lib/mirah/jvm/types/type_definition.rb +8 -2
  42. data/lib/mirah/transform/ast_ext.rb +9 -31
  43. data/lib/mirah/transform/transformer.rb +1 -1
  44. data/lib/mirah/typer.rb +2 -1
  45. data/lib/mirah/util/argument_processor.rb +10 -14
  46. data/lib/mirah/util/argument_processor.rb~ +146 -0
  47. data/lib/mirah/util/compilation_state.rb +15 -9
  48. data/lib/mirah/util/process_errors.rb +8 -2
  49. data/lib/mirah/version.rb +2 -2
  50. data/lib/mirah_task.rb +0 -7
  51. data/test/core/typer_test.rb +21 -13
  52. data/test/core/util/argument_processor_test.rb +19 -19
  53. data/test/core/util/class_loader_test.rb +19 -4
  54. data/test/core/util/compilation_state_test.rb +38 -0
  55. data/test/fixtures/org/foo/LowerCaseInnerClass$inner.class +0 -0
  56. data/test/fixtures/org/foo/LowerCaseInnerClass.class +0 -0
  57. data/test/fixtures/org/foo/LowerCaseInnerClass.java +7 -0
  58. data/test/jvm/blocks_test.rb +50 -29
  59. data/test/jvm/bytecode_test_helper.rb +71 -57
  60. data/test/jvm/cast_test.rb +162 -0
  61. data/test/jvm/constructors_test.rb +48 -0
  62. data/test/jvm/enumerable_test.rb +136 -7
  63. data/test/jvm/example_test.rb +39 -0
  64. data/test/jvm/factory_test.rb +6 -0
  65. data/test/jvm/generics_test.rb +0 -5
  66. data/test/jvm/import_test.rb +81 -0
  67. data/test/jvm/interface_test.rb +113 -0
  68. data/test/jvm/java_typer_test.rb +57 -11
  69. data/test/jvm/jvm_commands_test.rb +24 -0
  70. data/test/jvm/jvm_compiler_test.rb +186 -370
  71. data/test/jvm/macros_test.rb +67 -6
  72. data/test/jvm/main_method_test.rb +1 -1
  73. data/test/jvm/mirror_compilation_test_helper.rb +24 -0
  74. data/test/jvm/new_backend_test_helper.rb +25 -0
  75. data/test/jvm/rescue_test.rb +153 -18
  76. data/test/jvm/string_test.rb +41 -0
  77. data/test/jvm/varargs_test.rb +65 -0
  78. data/test/mirrors/base_type_test.rb +96 -0
  79. data/test/mirrors/bytecode_mirror_test.rb +86 -0
  80. data/test/mirrors/generics_test.rb +776 -0
  81. data/test/mirrors/member_test.rb +69 -0
  82. data/test/mirrors/method_lookup_test.rb +574 -0
  83. data/test/mirrors/mirrors_test.rb +562 -0
  84. data/test/mirrors/simple_async_mirror_loader_test.rb +110 -0
  85. data/test/mirrors/simple_mirror_loader_test.rb +104 -0
  86. data/test/test_helper.rb +2 -1
  87. metadata +244 -217
  88. data/README.txt +0 -59
  89. data/javalib/dynalink-0.2.jar +0 -0
  90. data/lib/mirah/jvm/typer.rb +0 -177
  91. data/lib/mirah/jvm/types/dynamic_type.rb +0 -45
  92. data/lib/mirah/jvm/types/unreachable_type.rb +0 -27
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 = []