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
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