mirah 0.0.12-java → 0.1.0-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. data/History.txt +372 -0
  2. data/README.txt +4 -5
  3. data/Rakefile +178 -55
  4. data/examples/appengine/Readme +3 -3
  5. data/examples/appengine/src/org/mirah/MirahApp.mirah +1 -1
  6. data/examples/appengine/src/org/mirah/list.dhtml +1 -1
  7. data/examples/bintrees.mirah +1 -1
  8. data/examples/edb.mirah +1 -1
  9. data/examples/fib.mirah +1 -1
  10. data/examples/interfaces.mirah +1 -1
  11. data/examples/macros/{string-each-char.mirah → string_each_char.mirah} +4 -5
  12. data/examples/maven/README.txt +1 -1
  13. data/examples/maven/src/main/mirah/hello_mirah.mirah +1 -1
  14. data/examples/plugins/appengine/Rakefile +1 -1
  15. data/examples/plugins/appengine/src/com/google/appengine/ext/duby/db/MetaModel.mirah +1 -1
  16. data/examples/plugins/appengine/src/com/google/appengine/ext/duby/db/Model.duby +1 -1
  17. data/examples/plugins/appengine/test/com/google/appengine/ext/duby/db/ModelTest.duby +1 -1
  18. data/examples/rosettacode/100-doors.mirah +6 -6
  19. data/examples/rosettacode/README.txt +3 -3
  20. data/examples/rosettacode/boolean-values.mirah +1 -1
  21. data/examples/rosettacode/comments.mirah +1 -1
  22. data/examples/rosettacode/count-occurrences-of-a-substring.mirah +1 -1
  23. data/examples/rosettacode/factorial.mirah +1 -1
  24. data/examples/rosettacode/fibonacci.mirah +1 -1
  25. data/examples/rosettacode/fizz-buzz.mirah +2 -2
  26. data/examples/rosettacode/flatten-a-list.mirah +4 -4
  27. data/examples/rosettacode/guess-the-number.mirah +2 -2
  28. data/examples/rosettacode/hamming-numbers.mirah +4 -4
  29. data/examples/rosettacode/is-string-numeric.mirah +22 -22
  30. data/examples/rosettacode/palindrome.mirah +2 -2
  31. data/examples/rosettacode/random-numbers.mirah +1 -1
  32. data/examples/rosettacode/repeat-a-string.mirah +1 -1
  33. data/examples/rosettacode/reverse-a-string.mirah +1 -1
  34. data/examples/rosettacode/rot-13.mirah +5 -5
  35. data/examples/rosettacode/secure-temporary-file.mirah +2 -2
  36. data/examples/rosettacode/sleep.mirah +1 -1
  37. data/examples/rosettacode/string-length.mirah +5 -5
  38. data/examples/swing.mirah +1 -1
  39. data/examples/test.edb +1 -1
  40. data/javalib/mirah-bootstrap.jar +0 -0
  41. data/javalib/mirah-builtins.jar +0 -0
  42. data/javalib/mirah-parser.jar +0 -0
  43. data/javalib/mirah-util.jar +0 -0
  44. data/lib/duby.rb +1 -1
  45. data/lib/mirah.rb +50 -28
  46. data/lib/mirah/ast.rb +15 -605
  47. data/lib/mirah/ast/scope.rb +98 -69
  48. data/lib/mirah/commands.rb +1 -1
  49. data/lib/mirah/commands/base.rb +7 -7
  50. data/lib/mirah/commands/compile.rb +3 -3
  51. data/lib/mirah/commands/parse.rb +7 -5
  52. data/lib/mirah/commands/run.rb +12 -19
  53. data/lib/mirah/compiler.rb +15 -23
  54. data/lib/mirah/errors.rb +16 -1
  55. data/lib/mirah/generator.rb +79 -39
  56. data/lib/mirah/jvm/compiler.rb +1 -19
  57. data/lib/mirah/jvm/compiler/base.rb +233 -90
  58. data/lib/mirah/jvm/compiler/jvm_bytecode.rb +675 -363
  59. data/lib/mirah/jvm/method_lookup.rb +134 -65
  60. data/lib/mirah/jvm/typer.rb +10 -5
  61. data/lib/mirah/jvm/types.rb +10 -2
  62. data/lib/mirah/jvm/types/array_type.rb +10 -12
  63. data/lib/mirah/{compiler/type.rb → jvm/types/ast_ext.rb} +12 -8
  64. data/lib/mirah/jvm/types/basic_types.rb +26 -33
  65. data/lib/mirah/jvm/types/bitescript_ext.rb +1 -1
  66. data/lib/mirah/jvm/types/block_type.rb +15 -0
  67. data/lib/mirah/jvm/types/boolean.rb +8 -4
  68. data/lib/mirah/jvm/types/dynamic_type.rb +12 -13
  69. data/lib/mirah/jvm/types/enumerable.rb +7 -7
  70. data/lib/mirah/jvm/types/extensions.rb +11 -6
  71. data/lib/mirah/jvm/types/factory.rb +624 -94
  72. data/lib/mirah/jvm/types/floats.rb +21 -15
  73. data/lib/mirah/jvm/types/generic_type.rb +72 -0
  74. data/lib/mirah/jvm/types/implicit_nil_type.rb +29 -0
  75. data/lib/mirah/jvm/types/integers.rb +26 -71
  76. data/lib/mirah/jvm/types/interface_definition.rb +3 -3
  77. data/lib/mirah/jvm/types/intrinsics.rb +203 -168
  78. data/lib/mirah/jvm/types/literals.rb +6 -6
  79. data/lib/mirah/jvm/types/meta_type.rb +13 -4
  80. data/lib/mirah/jvm/types/methods.rb +281 -93
  81. data/lib/mirah/jvm/types/null_type.rb +17 -5
  82. data/lib/mirah/jvm/types/number.rb +10 -7
  83. data/lib/mirah/jvm/types/primitive_type.rb +17 -6
  84. data/lib/mirah/jvm/types/source_mirror.rb +12 -7
  85. data/lib/mirah/jvm/types/type.rb +107 -23
  86. data/lib/mirah/jvm/types/type_definition.rb +25 -10
  87. data/lib/mirah/jvm/types/unreachable_type.rb +1 -1
  88. data/lib/mirah/jvm/types/void_type.rb +3 -3
  89. data/lib/mirah/parser.rb +154 -16
  90. data/lib/mirah/plugin/edb.rb +1 -1
  91. data/lib/mirah/transform.rb +1 -2
  92. data/lib/mirah/transform/ast_ext.rb +24 -43
  93. data/lib/mirah/transform/transformer.rb +29 -224
  94. data/lib/mirah/typer.rb +2 -16
  95. data/lib/mirah/util/argument_processor.rb +25 -10
  96. data/lib/mirah/util/class_loader.rb +1 -1
  97. data/lib/mirah/util/compilation_state.rb +16 -17
  98. data/lib/mirah/util/delegate.rb +2 -2
  99. data/lib/mirah/util/logging.rb +110 -0
  100. data/lib/mirah/util/process_errors.rb +69 -11
  101. data/lib/mirah/version.rb +1 -1
  102. data/test/core/commands_test.rb +6 -24
  103. data/test/core/env_test.rb +5 -5
  104. data/{lib/mirah/jvm/source_generator/typer.rb → test/core/generator_test.rb} +9 -9
  105. data/test/core/typer_test.rb +196 -158
  106. data/test/core/util/argument_processor_test.rb +10 -10
  107. data/test/core/util/class_loader_test.rb +6 -5
  108. data/test/fixtures/org/foo/LowerCaseInnerClass$inner.class +0 -0
  109. data/test/fixtures/org/foo/LowerCaseInnerClass.class +0 -0
  110. data/test/fixtures/org/foo/LowerCaseInnerClass.java +7 -0
  111. data/test/jvm/annotations_test.rb +5 -5
  112. data/test/jvm/blocks_test.rb +140 -88
  113. data/test/jvm/bytecode_test_helper.rb +112 -94
  114. data/test/jvm/cast_test.rb +162 -0
  115. data/test/jvm/constructors_test.rb +18 -8
  116. data/test/jvm/enumerable_test.rb +77 -44
  117. data/test/jvm/example_test.rb +53 -0
  118. data/test/jvm/factory_test.rb +7 -1
  119. data/test/jvm/generics_test.rb +57 -0
  120. data/test/jvm/hash_test.rb +106 -0
  121. data/test/jvm/import_test.rb +81 -0
  122. data/test/jvm/interface_test.rb +73 -0
  123. data/test/jvm/java_typer_test.rb +92 -66
  124. data/{lib/mirah/typer/base.rb → test/jvm/jvm_commands_test.rb} +6 -10
  125. data/test/jvm/jvm_compiler_test.rb +170 -604
  126. data/test/jvm/list_extensions_test.rb +23 -0
  127. data/test/jvm/macros_test.rb +197 -32
  128. data/test/jvm/main_method_test.rb +4 -4
  129. data/test/jvm/numeric_extensions_test.rb +13 -0
  130. data/test/jvm/rescue_test.rb +73 -16
  131. data/test/jvm/varargs_test.rb +65 -0
  132. data/test/test_helper.rb +1 -2
  133. metadata +234 -251
  134. data/examples/SortClosure$__xform_tmp_1.class +0 -0
  135. data/examples/SortClosure$__xform_tmp_2.class +0 -0
  136. data/examples/SortClosure.class +0 -0
  137. data/examples/macros/StringEachChar$Extension1.class +0 -0
  138. data/lib/mirah/ast/call.rb +0 -345
  139. data/lib/mirah/ast/class.rb +0 -359
  140. data/lib/mirah/ast/flow.rb +0 -381
  141. data/lib/mirah/ast/intrinsics.rb +0 -563
  142. data/lib/mirah/ast/literal.rb +0 -178
  143. data/lib/mirah/ast/local.rb +0 -112
  144. data/lib/mirah/ast/method.rb +0 -408
  145. data/lib/mirah/ast/structure.rb +0 -387
  146. data/lib/mirah/ast/type.rb +0 -146
  147. data/lib/mirah/commands/base.rb~ +0 -57
  148. data/lib/mirah/compiler/call.rb +0 -45
  149. data/lib/mirah/compiler/class.rb +0 -81
  150. data/lib/mirah/compiler/flow.rb +0 -109
  151. data/lib/mirah/compiler/literal.rb +0 -130
  152. data/lib/mirah/compiler/local.rb +0 -59
  153. data/lib/mirah/compiler/method.rb +0 -44
  154. data/lib/mirah/compiler/structure.rb +0 -65
  155. data/lib/mirah/jvm/compiler/java_source.rb +0 -787
  156. data/lib/mirah/jvm/method_lookup.rb~ +0 -247
  157. data/lib/mirah/jvm/source_generator/builder.rb +0 -468
  158. data/lib/mirah/jvm/source_generator/loops.rb +0 -131
  159. data/lib/mirah/jvm/source_generator/precompile.rb +0 -210
  160. data/lib/mirah/plugin/gwt.rb +0 -189
  161. data/lib/mirah/plugin/java.rb +0 -70
  162. data/lib/mirah/transform/error.rb +0 -13
  163. data/lib/mirah/transform/helper.rb +0 -765
  164. data/lib/mirah/typer/simple.rb +0 -384
  165. data/lib/mirah/version.rb~ +0 -18
  166. data/test/core/ast_test.rb +0 -382
  167. data/test/core/compilation_test.rb +0 -130
  168. data/test/core/macros_test.rb +0 -61
  169. data/test/jvm/javac_test_helper.rb +0 -89
  170. data/test/jvm/jvm_compiler_test.rb~ +0 -2181
  171. data/test/plugins/gwt_test.rb +0 -69
data/lib/mirah/errors.rb CHANGED
@@ -1,3 +1,18 @@
1
+ # Copyright (c) 2010 The Mirah project authors. All Rights Reserved.
2
+ # All contributing project authors may be found in the NOTICE file.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
1
16
  module Mirah
2
17
  class MirahError < StandardError
3
18
  attr_accessor :position
@@ -57,4 +72,4 @@ module Mirah
57
72
 
58
73
  class InternalCompilerError < NodeError
59
74
  end
60
- end
75
+ end
@@ -13,65 +13,105 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
  require 'mirah/util/process_errors'
16
+ require 'mirah/util/logging'
16
17
 
17
18
  module Mirah
18
19
  class Generator
19
20
  include Mirah::Util::ProcessErrors
21
+ include Mirah::Logging::Logged
22
+ java_import 'org.mirah.typer.simple.SimpleScoper'
23
+ java_import 'org.mirah.typer.simple.TypePrinter'
24
+ java_import 'org.mirah.macros.JvmBackend'
25
+
20
26
  def initialize(state, compiler_class, logging, verbose)
21
- @parser = Mirah::Parser.new(state, logging)
22
- @compiler = Mirah::Compiler::ASTCompiler.new(compiler_class, logging)
27
+ @state = state
28
+ @scoper = SimpleScoper.new {|scoper, node| Mirah::AST::StaticScope.new(node, scoper)}
29
+
30
+ # 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
34
+
35
+ @typer = Mirah::Typer::Typer.new(type_system, @scoper, self)
36
+ @parser = Mirah::Parser.new(state, @typer, logging)
37
+ @compiler = Mirah::Compiler::ASTCompiler.new(state, compiler_class, logging)
38
+ @extension_compiler = Mirah::Compiler::ASTCompiler.new(state, Mirah::JVM::Compiler::JVMBytecode, logging)
39
+ type_system.maybe_initialize_builtins(@typer.macro_compiler)
23
40
  @logging = logging
24
41
  @verbose = verbose
25
42
  end
26
-
27
- attr_accessor :parser, :compiler, :logging, :verbose
28
-
43
+
44
+ attr_accessor :parser, :compiler, :typer, :logging, :verbose
45
+
29
46
  def generate(arguments)
30
47
  # collect all ASTs from all files
31
48
  top_nodes = parser.parse_from_args(arguments)
32
-
49
+
33
50
  # enter all ASTs into inference engine
34
51
  puts "Inferring types..." if logging
35
- infer_asts(top_nodes)
36
-
52
+ scoper, typer = infer_asts(top_nodes)
53
+
37
54
  # compile each AST in turn
38
- compiler_results = compiler.compile_asts(top_nodes)
39
-
55
+ compiler_results = compiler.compile_asts(top_nodes, scoper, typer)
56
+
40
57
  puts "Done!" if logging
41
-
58
+
42
59
  compiler_results
43
60
  end
44
-
45
- def infer_asts(nodes)
46
- typer = Mirah::JVM::Typer.new(parser.transformer)
47
- nodes.each {|ast| typer.infer(ast, true) }
61
+
62
+ def infer_asts(nodes, should_raise=false)
48
63
  begin
49
- typer.resolve(false)
64
+ nodes.each {|ast| @typer.infer(ast, false) }
65
+ if should_raise
66
+ error_handler = lambda do |errors|
67
+ message, position = errors[0].message[0].to_a
68
+ raise Mirah::MirahError.new(message, position)
69
+ end
70
+ end
71
+ process_inference_errors(@typer, nodes, &error_handler)
72
+ rescue NativeException => ex
73
+ log("Caught exception during type inference", ex.cause)
74
+ raise ex
50
75
  ensure
51
- puts nodes.inspect if verbose
52
-
53
- failed = !typer.errors.empty?
54
- # extra_errors = []
55
- # nodes.each do |ast|
56
- # ast.each_descendant do |node|
57
- # if node.respond_to?(:inferred_type) && node.inferred_type && node.inferred_type.error?
58
- # extra_errors << node
59
- # end
60
- # end
61
- # end unless failed
62
- # unless extra_errors.empty?
63
- # typer_errors = typer.errors.map {|e| e.node}
64
- # new_errors = extra_errors - typer_errors
65
- # new_errors.each do |n|
66
- # typer.error(n)
67
- # end
68
- # failed = true
69
- # end
70
- if failed
71
- puts "Inference Error:"
72
- process_errors(typer.errors)
76
+ log_types(nodes)
77
+ end
78
+ [@scoper, @typer]
79
+ end
80
+
81
+ def log_types(nodes)
82
+ if self.logging?
83
+ buf = java.io.ByteArrayOutputStream.new
84
+ ps = java.io.PrintStream.new(buf)
85
+ printer = TypePrinter.new(@typer, ps)
86
+ nodes.each {|ast| printer.scan(ast, nil)}
87
+ ps.close()
88
+ log("Inferred types:\n{0}", java.lang.String.new(buf.toByteArray))
89
+ end
90
+
91
+ end
92
+
93
+ def compileAndLoadExtension(ast)
94
+ log_types([ast])
95
+ process_inference_errors(@typer, [ast])
96
+ results = @extension_compiler.compile_asts([ast], @scoper, @typer)
97
+ class_map = {}
98
+ first_class_name = nil
99
+ results.each do |result|
100
+ classname = result.classname.gsub(/\//, '.')
101
+ first_class_name ||= classname if classname.include?('$Extension')
102
+ class_map[classname] = Mirah::Util::ClassLoader.binary_string result.bytes
103
+ if @state.save_extensions
104
+ filename = "#{@state.destination}#{result.filename}"
105
+ FileUtils.mkdir_p(File.dirname(filename))
106
+ File.open(filename, 'wb') {|f| f.write(result.bytes)}
73
107
  end
74
108
  end
109
+ dcl = Mirah::Util::ClassLoader.new(JRuby.runtime.jruby_class_loader, class_map)
110
+ dcl.load_class(first_class_name)
111
+ end
112
+
113
+ def logExtensionAst(ast)
114
+ log("Extension ast:\n#{parser.format_ast(ast)}")
75
115
  end
76
116
  end
77
- end
117
+ end
@@ -17,8 +17,6 @@ require 'mirah'
17
17
  require 'mirah/jvm/compiler/base'
18
18
  require 'mirah/jvm/method_lookup'
19
19
  require 'mirah/jvm/types'
20
- require 'mirah/typer'
21
- require 'mirah/plugin/java'
22
20
  require 'bitescript'
23
21
  require 'mirah/jvm/compiler/jvm_bytecode'
24
22
 
@@ -27,25 +25,9 @@ module Mirah
27
25
  class FunctionalCall
28
26
  attr_accessor :target
29
27
  end
30
-
28
+
31
29
  class Super
32
30
  attr_accessor :target
33
31
  end
34
32
  end
35
33
  end
36
-
37
- if __FILE__ == $0
38
- Mirah::Typer.verbose = true
39
- Mirah::AST.verbose = true
40
- Mirah::JVM::Compiler::JVMBytecode.verbose = true
41
- ast = Mirah::AST.parse(File.read(ARGV[0]))
42
-
43
- typer = Mirah::Typer::Simple.new(:script)
44
- ast.infer(typer)
45
- typer.resolve(true)
46
-
47
- compiler = Mirah::JVM::Compiler::JVMBytecode.new(ARGV[0])
48
- compiler.compile(ast)
49
-
50
- compiler.generate
51
- end
@@ -16,33 +16,81 @@
16
16
  module Mirah
17
17
  module JVM
18
18
  module Compiler
19
- class Base
19
+ java_import 'mirah.lang.ast.ClassDefinition'
20
+ java_import 'mirah.lang.ast.StaticMethodDefinition'
21
+ java_import 'mirah.lang.ast.SimpleNodeVisitor'
22
+ java_import 'mirah.lang.ast.NodeScanner'
23
+
24
+ class Base < SimpleNodeVisitor
20
25
  attr_accessor :filename, :method, :static, :class
26
+ include Mirah::Logging::Logged
21
27
 
22
28
  class CompilationError < Mirah::NodeError
23
29
  end
24
30
 
25
- def initialize
31
+ def logger_name
32
+ "org.mirah.ruby.JVM.Compiler.Base"
33
+ end
34
+
35
+ def initialize(config, scoper, typer)
36
+ super()
37
+ @config = config
26
38
  @jump_scope = []
27
39
  @bindings = Hash.new {|h, type| h[type] = type.define(@file)}
28
40
  @captured_locals = Hash.new {|h, binding| h[binding] = {}}
29
41
  @self_scope = nil
42
+ @scoper = scoper
43
+ @typer = typer
30
44
  end
31
45
 
32
- def error(message, node)
33
- raise CompilationError.new(message, node)
46
+ def target_jvm_version
47
+ @config.target_jvm_version
48
+ end
49
+
50
+ def supports_invokedynamic?
51
+ @config.supports_invokedynamic?
52
+ end
53
+
54
+ def defaultNode(node, expression)
55
+ raise ArgumentError, "Can't compile node #{node}"
34
56
  end
35
57
 
36
- def compile(ast, expression = false)
58
+ def visit(node, expression)
37
59
  begin
38
- ast.compile(self, expression)
60
+ node.accept(self, expression)
39
61
  rescue Exception => ex
40
- raise Mirah::InternalCompilerError.wrap(ex, ast)
62
+ raise Mirah::InternalCompilerError.wrap(ex, node)
41
63
  end
42
- log "Compilation successful!"
43
64
  end
44
65
 
45
- def log(message); Mirah::JVM::Compiler::JVMBytecode.log(message); end
66
+ def get_scope(node)
67
+ @scoper.get_scope(node)
68
+ end
69
+
70
+ def introduced_scope(node)
71
+ @scoper.get_introduced_scope(node)
72
+ end
73
+
74
+ def containing_scope(node)
75
+ scope = get_scope(node)
76
+ name = node.name.identifier
77
+ while (!scope.shadowed?(name) && scope.parent && scope.parent.include?(name))
78
+ scope = scope.parent
79
+ end
80
+ scope
81
+ end
82
+
83
+ def inferred_type(node)
84
+ begin
85
+ @typer.get_inferred_type(node).resolve
86
+ rescue Exception => ex
87
+ raise Mirah::InternalCompilerError.wrap(ex, node)
88
+ end
89
+ end
90
+
91
+ def error(message, node)
92
+ raise CompilationError.new(message, node)
93
+ end
46
94
 
47
95
  def toplevel_class
48
96
  @class = @type.define(@file)
@@ -61,66 +109,119 @@ module Mirah
61
109
  log "...done!"
62
110
  end
63
111
 
64
- def define_main(script)
112
+ # Scans the top level of a file to see if it contains anything outside of a ClassDefinition.
113
+ class ScriptScanner < NodeScanner
114
+ attr_reader :found_other, :found_method
115
+ def enterDefault(node, arg)
116
+ @found_other = true
117
+ false
118
+ end
119
+ def enterMethodDefinition(node, arg)
120
+ @found_method = true
121
+ false
122
+ end
123
+ def enterStaticMethodDefinition(node, arg)
124
+ @found_method = true
125
+ false
126
+ end
127
+ def enterConstructorDefinition(node, arg)
128
+ @found_method = true
129
+ false
130
+ end
131
+ def enterPackage(node, arg)
132
+ # ignore
133
+ false
134
+ end
135
+ def enterClassDefinition(node, arg)
136
+ # ignore
137
+ false
138
+ end
139
+ def enterInterfaceDeclaration(node, arg)
140
+ # ignore
141
+ false
142
+ end
143
+ def enterImport(node, arg)
144
+ # ignore
145
+ false
146
+ end
147
+ def enterNodeList(node, arg)
148
+ # Scan the children
149
+ true
150
+ end
151
+ end
152
+
153
+ def visitMacroDefinition(node, expression)
154
+ # ignore. It was already compiled
155
+ end
156
+
157
+ def visitScript(script, expression)
65
158
  @static = true
66
- @filename = File.basename(script.filename)
159
+ @filename = File.basename(script.position.source.name)
67
160
  classname = Mirah::JVM::Compiler::JVMBytecode.classname_from_filename(@filename)
68
- @type = AST.type(script, classname)
161
+ @type = @typer.type_system.type(get_scope(script), classname)
69
162
  @file = file_builder(@filename)
70
-
71
- # Define a main method unless all of the script's children are 'top level'
72
- # nodes (e.g. Import, ClassDefinition, InterfaceDeclaration).
73
- unless script.body.children.all? { |c| c && c.top_level? }
163
+ body = script.body
164
+ scanner = ScriptScanner.new
165
+ scanner.scan(body, expression)
166
+ need_class = scanner.found_method || scanner.found_other
167
+ if need_class
74
168
  @class = @type.define(@file)
75
- with :method => @class.main do
76
- log "Starting main method"
77
-
78
- @method.start
79
- @current_scope = script.static_scope
80
- declare_locals(@current_scope)
81
- begin_main
169
+ if scanner.found_other
170
+ # Generate the main method
171
+ with :method => @class.main do
172
+ log "Starting main method"
173
+
174
+ @method.start
175
+ @current_scope = get_scope(script)
176
+ declare_locals(@current_scope)
177
+ begin_main
178
+
179
+ prepare_binding(script) do
180
+ visit(body, false)
181
+ end
82
182
 
83
- prepare_binding(script) do
84
- script.body.compile(self, false)
183
+ finish_main
184
+ @method.stop
85
185
  end
86
-
87
- finish_main
88
- @method.stop
186
+ log "Main method complete!"
187
+ else
188
+ visit(body, false)
89
189
  end
90
190
  @class.stop
91
-
92
- log "Main method complete!"
93
191
  else
94
- script.body.compile(self, false)
192
+ visit(body, false)
95
193
  end
96
194
  end
97
195
 
196
+ def visitNoop(node, expression)
197
+ end
198
+
98
199
  def begin_main; end
99
200
  def finish_main; end
100
201
 
101
202
  # arg_types must be an Array
102
203
  def create_method_builder(name, node, static, exceptions, return_type, arg_types)
103
- @class.build_method(name.to_s, node.visibility, static,
104
- exceptions, return_type, *arg_types)
204
+ visibility = :public # TODO
205
+ flags = BiteScript::ASM::Opcodes::ACC_PUBLIC
206
+ flags |= BiteScript::ASM::Opcodes::ACC_STATIC if static
207
+ flags |= BiteScript::ASM::Opcodes::ACC_ABSTRACT if node.annotated_abstract?
208
+ @class.method(flags, name.to_s, [return_type, *arg_types], exceptions)
105
209
  end
106
210
 
107
- def base_define_method(node, args_are_types)
108
- name, signature, args = node.name, node.signature, node.arguments.args
109
- if name == "initialize" && node.static?
211
+ def base_define_method(node)
212
+ name = node.name.identifier.sub(/=$/, '_set')
213
+ args = visit(node.arguments, true)
214
+ is_static = self.static || node.kind_of?(StaticMethodDefinition)
215
+ if name == "initialize" && is_static
110
216
  name = "<clinit>"
111
217
  end
112
- if args_are_types
113
- arg_types = args.map { |arg| arg.inferred_type } if args
114
- else
115
- arg_types = args
116
- end
117
- arg_types ||= []
118
- return_type = signature[:return]
119
- exceptions = signature[:throws]
218
+ arg_types = args.map { |arg| inferred_type(arg) }
219
+ return_type = inferred_type(node).return_type
220
+ exceptions = [] # TODO
120
221
 
121
- with :static => @static || node.static?, :current_scope => node.static_scope do
222
+ with :static => is_static, :current_scope => introduced_scope(node) do
122
223
  method = create_method_builder(name, node, @static, exceptions,
123
- return_type, arg_types)
224
+ return_type, arg_types)
124
225
  annotate(method, node.annotations)
125
226
  yield method, arg_types
126
227
  end
@@ -130,11 +231,7 @@ module Mirah
130
231
  if args
131
232
  args.each do |arg|
132
233
  if AST::OptionalArgument === arg
133
- new_args = if args_are_types
134
- arg_types_for_opt
135
- else
136
- args_for_opt
137
- end
234
+ new_args = arg_types_for_opt
138
235
  method = create_method_builder(name, node, @static, exceptions,
139
236
  return_type, new_args)
140
237
  with :method => method do
@@ -151,68 +248,90 @@ module Mirah
151
248
  @method.stop
152
249
  end
153
250
  end
154
- arg_types_for_opt << arg.inferred_type
251
+ arg_types_for_opt << inferred_type(arg)
155
252
  args_for_opt << arg
156
253
  end
157
254
  end
158
255
  end
159
256
 
160
- def constructor(node, args_are_types)
161
- args = node.arguments.args || []
162
- arg_types = if args_are_types
163
- args.map { |arg| arg.inferred_type }
164
- else
165
- args
166
- end
167
- exceptions = node.signature[:throws]
168
- method = @class.build_constructor(node.visibility, exceptions, *arg_types)
257
+ def visitConstructorDefinition(node, expression)
258
+ args = visit(node.arguments, true)
259
+ arg_types = args.map { |arg| inferred_type(arg) }
260
+ exceptions = [] # node.signature[:throws]
261
+ visibility = :public # node.visibility
262
+ method = @class.build_constructor(visibility, exceptions, *arg_types)
169
263
  annotate(method, node.annotations)
170
- with :current_scope => node.static_scope do
264
+ with :current_scope => introduced_scope(node) do
171
265
  yield(method, args)
172
266
  end
173
267
  end
174
268
 
175
- def define_class(class_def, expression)
176
- with(:type => class_def.inferred_type,
177
- :class => class_def.inferred_type.define(@file),
178
- :static => false) do
269
+ def visitClassDefinition(class_def, expression)
270
+ log "Compiling class #{class_def.name.identifier}"
271
+ with(:type => inferred_type(class_def),
272
+ :class => inferred_type(class_def).define(@file),
273
+ :static => false) do
179
274
  annotate(@class, class_def.annotations)
180
- class_def.body.compile(self, false) if class_def.body
275
+ visit(class_def.body, false) if class_def.body
181
276
  @class.stop
182
277
  end
183
278
  end
184
279
 
185
- def declare_argument(name, type)
186
- # declare local vars for arguments here
280
+ def visitArguments(args, expression)
281
+ result = []
282
+ args.required.each {|arg| result << arg}
283
+ args.optional.each {|arg| result << arg}
284
+ result << args.rest if args.rest
285
+ args.required2.each {|arg| result << arg}
286
+ result << args.block if args.block
287
+ result
288
+ end
289
+
290
+ def visitStaticMethodDefinition(mdef, expression)
291
+ visitMethodDefinition(mdef, expression)
187
292
  end
188
293
 
189
- def body(body, expression)
294
+ def visitNodeList(body, expression)
190
295
  saved_self = @self_scope
191
- if body.kind_of?(Mirah::AST::ScopedBody)
192
- scope = body.static_scope
193
- declare_locals(scope)
194
- if scope != @self_scope
195
- if scope.self_node && scope.self_node != :self
296
+ new_scope = introduced_scope(body)
297
+ if new_scope
298
+ declare_locals(new_scope)
299
+ if new_scope != @self_scope
300
+ if new_scope.self_node && new_scope.self_node != :self
196
301
  # FIXME This is a horrible hack!
197
302
  # Instead we should eliminate unused self's.
198
- unless scope.self_type.name == 'mirah.impl.Builtin'
303
+ unless new_scope.self_type.name == 'mirah.impl.Builtin'
199
304
  local_assign(
200
- scope, 'self', scope.self_type, false, scope.self_node)
305
+ new_scope, 'self', new_scope.self_type, false, new_scope.self_node)
201
306
  end
202
307
  end
203
- @self_scope = scope
308
+ @self_scope = new_scope
204
309
  end
205
310
  end
206
311
  # all except the last element in a body of code is treated as a statement
207
- i, last = 0, body.children.size - 1
312
+ i, last = 0, body.size - 1
208
313
  while i < last
209
- body.children[i].compile(self, false)
314
+ visit(body.get(i), false)
210
315
  i += 1
211
316
  end
212
- yield body.children[last] if last >= 0
317
+ if last >= 0
318
+ yield body.get(last)
319
+ else
320
+ yield nil
321
+ end
213
322
  @self_scope = saved_self
214
323
  end
215
324
 
325
+ def visitClassAppendSelf(node, expression)
326
+ with :static => true, :current_scope => introduced_scope(node) do
327
+ visit(node.body, expression)
328
+ end
329
+ end
330
+
331
+ def visitPackage(node, expression)
332
+ visit(node.body, expression) if node.body
333
+ end
334
+
216
335
  def scoped_body(scope, expression)
217
336
  body(scope, expression)
218
337
  end
@@ -225,19 +344,43 @@ module Mirah
225
344
  end
226
345
  end
227
346
 
228
- def import(short, long)
347
+ def visitImport(node, expression)
229
348
  end
230
349
 
231
- def fixnum(type, value)
232
- type.literal(method, value)
350
+ def visitFixnum(node, expression)
351
+ if expression
352
+ inferred_type(node).literal(method, node.value)
353
+ end
354
+ end
355
+ alias visitFloat visitFixnum
356
+
357
+ def visitSelf(node, expression)
358
+ if expression
359
+ set_position(node.position)
360
+ scope = get_scope(node)
361
+ if scope.self_node && scope.self_node != :self
362
+ local(scope, 'self', scope.self_type)
363
+ else
364
+ real_self
365
+ end
366
+ end
367
+ end
368
+
369
+ def visitImplicitSelf(node, expression)
370
+ visitSelf(node, expression)
233
371
  end
234
- alias float fixnum
235
372
 
236
- def compile_self
237
- if @self_scope && @self_scope.self_node && @self_scope.self_node != :self
238
- local(@self_scope, 'self', @self_scope.self_type)
373
+ def visitUnquote(node, expression)
374
+ body = node.nodes
375
+ i, last = 0, body.size - 1
376
+ while i < last
377
+ visit(body.get(i), false)
378
+ i += 1
379
+ end
380
+ if last >= 0
381
+ visit(body.get(last), expression)
239
382
  else
240
- real_self
383
+ visitImplicitNil(node, expression)
241
384
  end
242
385
  end
243
386
 
@@ -267,4 +410,4 @@ module Mirah
267
410
  end
268
411
  end
269
412
  end
270
- end
413
+ end