Skip to content
This repository
Browse code

Start getting jvm compiler to work

  • Loading branch information...
commit df1f9db4cd657d209cb034cd3fcde7c52dd439b5 1 parent bbb3423
ribrdb authored July 19, 2011
2  examples/fib.mirah
@@ -13,7 +13,7 @@
13 13
 # See the License for the specific language governing permissions and
14 14
 # limitations under the License.
15 15
 
16  
-def fib(a:int):int
  16
+def fib(a:int)
17 17
   if a < 2
18 18
     a
19 19
   else
BIN  javalib/mirah-parser.jar
Binary file not shown
4  lib/mirah.rb
@@ -61,7 +61,7 @@ def self.print_error(message, position)
61 61
       puts message
62 62
       return
63 63
     end
64  
-    puts "#{position.file}:#{position.start_line}: #{message}"
65  
-    puts position.underline
  64
+    puts "#{position.filename}:#{position.start_line}: #{message}"
  65
+    #puts position.underline
66 66
   end
67 67
 end
38  lib/mirah/compiler.rb
@@ -13,15 +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/compiler/call'
17  
-require 'mirah/compiler/class'
18  
-require 'mirah/compiler/flow'
19  
-require 'mirah/compiler/literal'
20  
-require 'mirah/compiler/local'
21  
-require 'mirah/compiler/method'
22  
-require 'mirah/compiler/structure'
23  
-require 'mirah/compiler/type'
24  
-
25 16
 module Mirah
26 17
   module Compiler
27 18
     class ASTCompiler
@@ -29,34 +20,43 @@ def initialize(compiler_class, logging)
29 20
         @compiler_class = compiler_class
30 21
         @logging = logging
31 22
       end
32  
-      
33  
-      attr_accessor :compiler_class, :logging
34  
-      
  23
+
  24
+      attr_accessor :compiler_class, :compiler, :logging
  25
+
35 26
       def compile_asts(nodes, scoper)
36 27
         results = []
37 28
         puts "Compiling..." if logging
38 29
         nodes.each do |ast|
39  
-          puts "  #{ast.position.file}" if logging
  30
+          puts "  #{ast.position.filename}" if logging
40 31
           compile_ast(ast, scoper) do |filename, builder|
41 32
             results << CompilerResult.new(filename, builder.class_name, builder.generate)
42 33
           end
43 34
         end
44 35
         results
45 36
       end
46  
-      
  37
+
47 38
       def compile_ast(ast, scoper, &block)
48  
-        compiler = compiler_class.new(scoper)
49  
-        ast.compile(compiler, false)
  39
+        @compiler = compiler_class.new(scoper)
  40
+        compiler.visit(ast, nil)
50 41
         compiler.generate(&block)
51 42
       end
52 43
     end
53  
-    
  44
+
54 45
     class CompilerResult
55 46
       def initialize(filename, classname, bytes)
56 47
         @filename, @classname, @bytes = filename, classname, bytes
57 48
       end
58  
-      
  49
+
59 50
       attr_accessor :filename, :classname, :bytes
60 51
     end
61 52
   end
62  
-end
  53
+end
  54
+
  55
+require 'mirah/compiler/call'
  56
+require 'mirah/compiler/class'
  57
+require 'mirah/compiler/flow'
  58
+require 'mirah/compiler/literal'
  59
+require 'mirah/compiler/local'
  60
+require 'mirah/compiler/method'
  61
+require 'mirah/compiler/structure'
  62
+require 'mirah/compiler/type'
45  lib/mirah/compiler/call.rb
... ...
@@ -1,45 +0,0 @@
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  
-
16  
-module Mirah
17  
-  module AST
18  
-    class FunctionalCall
19  
-      def compile(compiler, expression)
20  
-        compiler.line(line_number)
21  
-        compiler.self_call(self, expression)
22  
-      rescue Exception => ex
23  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
24  
-      end
25  
-    end
26  
-
27  
-    class Call
28  
-      def compile(compiler, expression)
29  
-        compiler.line(line_number)
30  
-        compiler.call(self, expression)
31  
-      rescue Exception => ex
32  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
33  
-      end
34  
-    end
35  
-
36  
-    class Super
37  
-      def compile(compiler, expression)
38  
-        compiler.line(line_number)
39  
-        compiler.super_call(self, expression)
40  
-      rescue Exception => ex
41  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
42  
-      end
43  
-    end
44  
-  end
45  
-end
81  lib/mirah/compiler/class.rb
... ...
@@ -1,81 +0,0 @@
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  
-
16  
-module Mirah
17  
-  module AST
18  
-    class ClassDefinition
19  
-      def compile(compiler, expression)
20  
-        compiler.define_class(self, expression)
21  
-      rescue Exception => ex
22  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
23  
-      end
24  
-    end
25  
-    
26  
-    class ClosureDefinition
27  
-      def compile(compiler, expression)
28  
-        compiler.define_closure(self, expression)
29  
-      rescue Exception => ex
30  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
31  
-      end
32  
-    end
33  
-
34  
-    class AccessLevel
35  
-      def compile(compiler, expression); end
36  
-    end
37  
-
38  
-    class FieldDeclaration
39  
-      def compile(compiler, expression)
40  
-        compiler.field_declare(name, inferred_type, annotations, static)
41  
-      rescue Exception => ex
42  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
43  
-      end
44  
-    end
45  
-
46  
-    class FieldAssignment
47  
-      def compile(compiler, expression)
48  
-        compiler.line(line_number)
49  
-        compiler.field_assign(name, inferred_type, expression, value, annotations, static)
50  
-      rescue Exception => ex
51  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
52  
-      end
53  
-    end
54  
-
55  
-    class Field
56  
-      def compile(compiler, expression)
57  
-        compiler.line(line_number)
58  
-        if expression
59  
-          compiler.field(name, inferred_type, annotations, static)
60  
-        end
61  
-      rescue Exception => ex
62  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
63  
-      end
64  
-    end
65  
-
66  
-    class Include
67  
-      def compile(compiler, expression); end
68  
-    end
69  
-    
70  
-    class Constant
71  
-      def compile(compiler, expression)
72  
-        if expression
73  
-          compiler.line(line_number)
74  
-          compiler.constant(self)
75  
-        end
76  
-      rescue Exception => ex
77  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
78  
-      end
79  
-    end
80  
-  end
81  
-end
109  lib/mirah/compiler/flow.rb
... ...
@@ -1,109 +0,0 @@
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  
-
16  
-module Mirah
17  
-  module AST
18  
-    class If
19  
-      def compile(compiler, expression)
20  
-        compiler.line(line_number)
21  
-        compiler.branch(self, expression)
22  
-      rescue Exception => ex
23  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
24  
-      end
25  
-    end
26  
-
27  
-    class Condition
28  
-      def compile(compiler, expression)
29  
-        # TODO: can a condition ever be an expression? I don't think it can...
30  
-        compiler.line(line_number)
31  
-        predicate.compile(compiler, expression)
32  
-      rescue Exception => ex
33  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
34  
-      end
35  
-    end
36  
-
37  
-    class Loop
38  
-      def compile(compiler, expression)
39  
-        compiler.line(line_number)
40  
-        compiler.loop(self, expression)
41  
-      rescue Exception => ex
42  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
43  
-      end
44  
-    end
45  
-
46  
-    class Return
47  
-      def compile(compiler, expression)
48  
-        compiler.line(line_number)
49  
-        compiler.return(self)
50  
-      rescue Exception => ex
51  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
52  
-      end
53  
-    end
54  
-
55  
-    class Break
56  
-      def compile(compiler, expression)
57  
-        compiler.line(line_number)
58  
-        compiler.break(self)
59  
-      rescue Exception => ex
60  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
61  
-      end
62  
-    end
63  
-
64  
-    class Next
65  
-      def compile(compiler, expression)
66  
-        compiler.line(line_number)
67  
-        compiler.next(self)
68  
-      rescue Exception => ex
69  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
70  
-      end
71  
-    end
72  
-
73  
-    class Redo
74  
-      def compile(compiler, expression)
75  
-        compiler.line(line_number)
76  
-        compiler.redo(self)
77  
-      rescue Exception => ex
78  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
79  
-      end
80  
-    end
81  
-
82  
-    class Raise
83  
-      def compile(compiler, expression)
84  
-        compiler.line(line_number)
85  
-        compiler._raise(exception)
86  
-      rescue Exception => ex
87  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
88  
-      end
89  
-    end
90  
-
91  
-    class Rescue
92  
-      def compile(compiler, expression)
93  
-        compiler.line(line_number)
94  
-        compiler.rescue(self, expression)
95  
-      rescue Exception => ex
96  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
97  
-      end
98  
-    end
99  
-
100  
-    class Ensure
101  
-      def compile(compiler, expression)
102  
-        compiler.line(line_number)
103  
-        compiler.ensure(self, expression)
104  
-      rescue Exception => ex
105  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
106  
-      end
107  
-    end
108  
-  end
109  
-end
130  lib/mirah/compiler/literal.rb
... ...
@@ -1,130 +0,0 @@
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  
-
16  
-module Mirah
17  
-  module AST
18  
-    class Fixnum
19  
-      def compile(compiler, expression)
20  
-        if expression
21  
-          compiler.line(line_number)
22  
-          compiler.fixnum(inferred_type, literal)
23  
-        end
24  
-      rescue Exception => ex
25  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
26  
-      end
27  
-    end
28  
-
29  
-    class Regexp
30  
-      def compile(compiler, expression)
31  
-        if expression
32  
-          compiler.line(line_number)
33  
-          compiler.regexp(literal)
34  
-        end
35  
-      rescue Exception => ex
36  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
37  
-      end
38  
-    end
39  
-
40  
-    class String
41  
-      def compile(compiler, expression)
42  
-        if expression
43  
-          compiler.line(line_number)
44  
-          compiler.string(literal)
45  
-        end
46  
-      rescue Exception => ex
47  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
48  
-      end
49  
-    end
50  
-
51  
-    class StringConcat
52  
-      def compile(compiler, expression)
53  
-        compiler.build_string(children, expression)
54  
-      rescue Exception => ex
55  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
56  
-      end
57  
-    end
58  
-
59  
-    class ToString
60  
-      def compile(compiler, expression)
61  
-        compiler.to_string(body, expression)
62  
-      rescue Exception => ex
63  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
64  
-      end
65  
-    end
66  
-
67  
-    class Float
68  
-      def compile(compiler, expression)
69  
-        if expression
70  
-          compiler.line(line_number)
71  
-          compiler.float(inferred_type, literal)
72  
-        end
73  
-      rescue Exception => ex
74  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
75  
-      end
76  
-    end
77  
-
78  
-    class Boolean
79  
-      def compile(compiler, expression)
80  
-        if expression
81  
-          compiler.line(line_number)
82  
-          compiler.boolean(literal)
83  
-        end
84  
-      rescue Exception => ex
85  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
86  
-      end
87  
-    end
88  
-
89  
-    class Array
90  
-      def compile(compiler, expression)
91  
-        compiler.array(self, expression)
92  
-      rescue Exception => ex
93  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
94  
-      end
95  
-    end
96  
-
97  
-    class Null
98  
-      def compile(compiler, expression)
99  
-        if expression
100  
-          compiler.line(line_number)
101  
-          compiler.null
102  
-        end
103  
-      rescue Exception => ex
104  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
105  
-      end
106  
-    end
107  
-
108  
-    class EmptyArray
109  
-      def compile(compiler, expression)
110  
-        if expression
111  
-          compiler.line(line_number)
112  
-          compiler.empty_array(component_type, size)
113  
-        end
114  
-      rescue Exception => ex
115  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
116  
-      end
117  
-    end
118  
-
119  
-    class Self
120  
-      def compile(compiler, expression)
121  
-        if expression
122  
-          compiler.line(line_number)
123  
-          compiler.compile_self(compiler.get_scope(self))
124  
-        end
125  
-      rescue Exception => ex
126  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
127  
-      end
128  
-    end
129  
-  end
130  
-end
62  lib/mirah/compiler/local.rb
... ...
@@ -1,62 +0,0 @@
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  
-
16  
-module Mirah
17  
-  module AST
18  
-    class LocalDeclaration
19  
-      def compile(compiler, expression)
20  
-        compiler.line(line_number)
21  
-        scope = compiler.get_scope(self)
22  
-        if scope.captured?(name) && scope.has_binding?
23  
-          compiler.captured_local_declare(compiler.containing_scope(self), name, type)
24  
-        else
25  
-          compiler.local_declare(compiler.containing_scope(self), name, type)
26  
-        end
27  
-      rescue Exception => ex
28  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
29  
-      end
30  
-    end
31  
-
32  
-    class LocalAssignment
33  
-      def compile(compiler, expression)
34  
-        compiler.line(line_number)
35  
-        scope = compiler.get_scope(self)
36  
-        if scope.captured?(name) && scope.has_binding?
37  
-          compiler.captured_local_assign(self, expression)
38  
-        else
39  
-          compiler.local_assign(compiler.containing_scope(self), name, inferred_type, expression, value)
40  
-        end
41  
-      rescue Exception => ex
42  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
43  
-      end
44  
-    end
45  
-
46  
-    class Local
47  
-      def compile(compiler, expression)
48  
-        if expression
49  
-          compiler.line(line_number)
50  
-          scope = compiler.get_scope(self)
51  
-          if scope.captured?(name) && scope.has_binding?
52  
-            compiler.captured_local(compiler.containing_scope(self), name, inferred_type)
53  
-          else
54  
-            compiler.local(compiler.containing_scope(self), name, inferred_type)
55  
-          end
56  
-        end
57  
-      rescue Exception => ex
58  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
59  
-      end
60  
-    end
61  
-  end
62  
-end
44  lib/mirah/compiler/method.rb
... ...
@@ -1,44 +0,0 @@
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  
-
16  
-module Mirah
17  
-  module AST
18  
-    class Arguments
19  
-      def compile(compiler, expression)
20  
-        # TODO: what does it mean for a method to be an expression?
21  
-        args.each {|arg| compiler.declare_argument(arg.name, arg.inferred_type)} if args
22  
-      rescue Exception => ex
23  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
24  
-      end
25  
-    end
26  
-
27  
-    class MethodDefinition
28  
-      def compile(compiler, expression)
29  
-        # TODO: what does it mean for a method to be an expression?
30  
-        compiler.define_method(self)
31  
-      rescue Exception => ex
32  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
33  
-      end
34  
-    end
35  
-
36  
-    class ConstructorDefinition
37  
-      def compile(compiler, expression)
38  
-        compiler.constructor(self)
39  
-      rescue Exception => ex
40  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
41  
-      end
42  
-    end
43  
-  end
44  
-end
56  lib/mirah/compiler/structure.rb
... ...
@@ -1,56 +0,0 @@
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  
-
16  
-module Mirah
17  
-  module AST
18  
-    class Body
19  
-      def compile(compiler, expression)
20  
-        compiler.line(line_number)
21  
-        compiler.body(self, expression)
22  
-      rescue Exception => ex
23  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
24  
-      end
25  
-    end
26  
-
27  
-    class BindingReference
28  
-      def compile(compiler, expression)
29  
-        if expression
30  
-          compiler.line(line_number)
31  
-          compiler.binding_reference
32  
-        end
33  
-      rescue Exception => ex
34  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
35  
-      end
36  
-    end
37  
-    
38  
-    class Script
39  
-      def compile(compiler, expression)
40  
-        # TODO: what does it mean for a script to be an expression? possible?
41  
-        compiler.define_main(self)
42  
-      rescue Exception => ex
43  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
44  
-      end
45  
-    end
46  
-    
47  
-    class Noop
48  
-      def compile(compiler, expression)
49  
-        # TODO: what does it mean for a noop to be an expression
50  
-        # nothing
51  
-      rescue Exception => ex
52  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
53  
-      end
54  
-    end
55  
-  end
56  
-end
27  lib/mirah/compiler/type.rb
... ...
@@ -1,27 +0,0 @@
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  
-
16  
-module Mirah
17  
-  module AST
18  
-    class Import
19  
-      def compile(compiler, expression)
20  
-        # TODO: what does it mean for import to be an expression?
21  
-        compiler.import(short, long)
22  
-      rescue Exception => ex
23  
-        raise Mirah::InternalCompilerError.wrap(ex, self)
24  
-      end
25  
-    end
26  
-  end
27  
-end
21  lib/mirah/generator.rb
@@ -17,6 +17,9 @@
17 17
 module Mirah
18 18
   class Generator
19 19
     include Mirah::Util::ProcessErrors
  20
+    java_import 'org.mirah.typer.simple.SimpleScoper'
  21
+    java_import 'org.mirah.typer.simple.TypePrinter'
  22
+
20 23
     def initialize(state, compiler_class, logging, verbose)
21 24
       @parser = Mirah::Parser.new(state, logging)
22 25
       @compiler = Mirah::Compiler::ASTCompiler.new(compiler_class, logging)
@@ -32,10 +35,10 @@ def generate(arguments)
32 35
       
33 36
       # enter all ASTs into inference engine
34 37
       puts "Inferring types..." if logging
35  
-      infer_asts(top_nodes)
  38
+      scoper = infer_asts(top_nodes)
36 39
       
37 40
       # compile each AST in turn
38  
-      compiler_results = compiler.compile_asts(top_nodes, parser.transformer)
  41
+      compiler_results = compiler.compile_asts(top_nodes, scoper)
39 42
       
40 43
       puts "Done!" if logging
41 44
       
@@ -43,15 +46,19 @@ def generate(arguments)
43 46
     end
44 47
 
45 48
     def infer_asts(nodes)
46  
-      scoper = Mirah::Types::Scoper.new
47  
-      type_system = Mirah::Types::SimpleTypes.new
48  
-      typer = Mirah::Types::Typer::Typer.new(type_system, scoper)
  49
+      scoper = SimpleScoper.new {|scoper, node| Mirah::AST::StaticScope.new(node, scoper)}
  50
+      type_system = Mirah::JVM::Types::TypeFactory.new
  51
+      typer = Mirah::Typer::Typer.new(type_system, scoper)
49 52
       begin
50 53
         nodes.each {|ast| typer.infer(ast, false) }
51  
-        process_inference_errors(nodes)
  54
+        process_inference_errors(typer, nodes)
52 55
       ensure
53  
-        puts nodes.inspect if verbose
  56
+        if verbose
  57
+          printer = TypePrinter.new(typer)
  58
+          nodes.each {|ast| printer.scan(ast, nil)}
  59
+        end
54 60
       end
  61
+      scoper
55 62
     end
56 63
   end
57 64
 end
137  lib/mirah/jvm/compiler/base.rb
@@ -16,7 +16,10 @@
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
+      class Base < SimpleNodeVisitor
20 23
         attr_accessor :filename, :method, :static, :class
21 24
 
22 25
         class CompilationError < Mirah::NodeError
@@ -27,20 +30,23 @@ def initialize(scoper)
27 30
           @bindings = Hash.new {|h, type| h[type] = type.define(@file)}
28 31
           @captured_locals = Hash.new {|h, binding| h[binding] = {}}
29 32
           @self_scope = nil
30  
-          self.scopes = scoper.scopes
  33
+          @scoper = scoper
31 34
         end
32 35
 
33  
-        def error(message, node)
34  
-          raise CompilationError.new(message, node)
  36
+        def defaultNode(node, expression)
  37
+          raise ArgumentError, "Can't compile node #{node}"
35 38
         end
36 39
 
37  
-        def compile(ast, expression = false)
  40
+        def visit(node, expression)
38 41
           begin
39  
-            ast.compile(self, expression)
40  
-          rescue => ex
41  
-            raise Mirah::InternalCompilerError.wrap(ex, ast)
  42
+            super(node, expression)
  43
+          rescue Exception => ex
  44
+            raise Mirah::InternalCompilerError.wrap(ex, node)
42 45
           end
43  
-          log "Compilation successful!"
  46
+        end
  47
+
  48
+        def error(message, node)
  49
+          raise CompilationError.new(message, node)
44 50
         end
45 51
 
46 52
         def log(message); Mirah::JVM::Compiler::JVMBytecode.log(message); end
@@ -62,15 +68,15 @@ def generate
62 68
           log "...done!"
63 69
         end
64 70
 
65  
-        def define_main(script)
  71
+        def visitScript(script, expression)
66 72
           @static = true
67  
-          @filename = File.basename(script.filename)
  73
+          @filename = File.basename(script.position.filename)
68 74
           classname = Mirah::JVM::Compiler::JVMBytecode.classname_from_filename(@filename)
69 75
           @type = AST.type(get_scope(script), classname)
70 76
           @file = file_builder(@filename)
71 77
           body = script.body
72  
-          body = body[0] if body.children.size == 1
73  
-          if body.class != AST::ClassDefinition
  78
+          body = body[0] if body.size == 1
  79
+          if body.class != ClassDefinition
74 80
             @class = @type.define(@file)
75 81
             with :method => @class.main do
76 82
               log "Starting main method"
@@ -81,7 +87,7 @@ def define_main(script)
81 87
               begin_main
82 88
 
83 89
               prepare_binding(script) do
84  
-                body.compile(self, false)
  90
+                visit(body, false)
85 91
               end
86 92
 
87 93
               finish_main
@@ -89,12 +95,15 @@ def define_main(script)
89 95
             end
90 96
             @class.stop
91 97
           else
92  
-            body.compile(self, false)
  98
+            visit(body, false)
93 99
           end
94 100
 
95 101
           log "Main method complete!"
96 102
         end
97 103
 
  104
+        def visitNoop(node, expression)
  105
+        end
  106
+
98 107
         def begin_main; end
99 108
         def finish_main; end
100 109
 
@@ -104,23 +113,20 @@ def create_method_builder(name, node, static, exceptions, return_type, arg_types
104 113
           exceptions, return_type, *arg_types)
105 114
         end
106 115
 
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?
  116
+        def base_define_method(node)
  117
+          name = node.name.identifier
  118
+          args = visit(node.arguments, true)
  119
+          is_static = self.static || node.kind_of?(StaticMethodDefinition)
  120
+          if name == "initialize" && is_static
110 121
             name = "<clinit>"
111 122
           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]
  123
+          arg_types = args.map { |arg| inferred_type(arg) }
  124
+          return_type = inferred_type(node)
  125
+          # TODO exceptions
120 126
 
121  
-          with :static => @static || node.static?, :current_scope => introduced_scope(node) do
  127
+          with :static => is_static, :current_scope => introduced_scope(node) do
122 128
             method = create_method_builder(name, node, @static, exceptions,
123  
-            return_type, arg_types)
  129
+                                           return_type, arg_types)
124 130
             annotate(method, node.annotations)
125 131
             yield method, arg_types
126 132
           end
@@ -151,42 +157,49 @@ def base_define_method(node, args_are_types)
151 157
                   @method.stop
152 158
                 end
153 159
               end
154  
-              arg_types_for_opt << arg.inferred_type
  160
+              arg_types_for_opt << inferred_type(arg)
155 161
               args_for_opt << arg
156 162
             end
157 163
           end
158 164
         end
159 165
 
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)
  166
+        def visitConstructorDefinition(node, expression)
  167
+          args = visit(node.arguments, true)
  168
+          arg_types = args.map { |arg| inferred_type(arg) }
  169
+          exceptions = []  # node.signature[:throws]
  170
+          visibility = :public  # node.visibility
  171
+          method = @class.build_constructor(visibility, exceptions, *arg_types)
169 172
           annotate(method, node.annotations)
170 173
           with :current_scope => introduced_scope(node) do
171 174
             yield(method, args)
172 175
           end
173 176
         end
174 177
 
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
  178
+        def visitClassDefinition(class_def, expression)
  179
+          with(:type => inferred_type(class_def),
  180
+               :class => inferred_type(class_def).define(@file),
  181
+               :static => false) do
179 182
             annotate(@class, class_def.annotations)
180  
-            class_def.body.compile(self, false) if class_def.body
  183
+            visit(class_def.body, false) if class_def.body
181 184
             @class.stop
182 185
           end
183 186
         end
184 187
 
185  
-        def declare_argument(name, type)
186  
-          # declare local vars for arguments here
  188
+        def visitArguments(args, expression)
  189
+          result = []
  190
+          args.required.each {|arg| result << arg}
  191
+          args.optional.each {|arg| result << arg}
  192
+          result << args.rest if args.rest
  193
+          args.required2.each {|arg| result << arg}
  194
+          result << args.block if args.block
  195
+          result
187 196
         end
188 197
 
189  
-        def body(body, expression)
  198
+        def visitStaticMethodDefinition(mdef, expression)
  199
+          visitMethodDefinition(mdef, expression)
  200
+        end
  201
+
  202
+        def visitNodeList(body, expression)
190 203
           saved_self = @self_scope
191 204
           new_scope = introduced_scope(body)
192 205
           if new_scope
@@ -204,12 +217,12 @@ def body(body, expression)
204 217
             end
205 218
           end
206 219
           # all except the last element in a body of code is treated as a statement
207  
-          i, last = 0, body.children.size - 1
  220
+          i, last = 0, body.size - 1
208 221
           while i < last
209  
-            body.children[i].compile(self, false)
  222
+            visit(body.get(i), false)
210 223
             i += 1
211 224
           end
212  
-          yield body.children[last] if last >= 0
  225
+          yield body.children[last]
213 226
           @self_scope = saved_self
214 227
         end
215 228
 
@@ -225,19 +238,25 @@ def scoped_local_name(name, scope=nil)
225 238
           end
226 239
         end
227 240
 
228  
-        def import(short, long)
  241
+        def visitImport(node, expression)
229 242
         end
230 243
 
231  
-        def fixnum(type, value)
232  
-          type.literal(method, value)
  244
+        def visitFixnum(node, expression)
  245
+          if expression
  246
+            inferred_type(node).literal(method, node.value)
  247
+          end
233 248
         end
234  
-        alias float fixnum
235  
-
236  
-        def compile_self(scope)
237  
-          if scope.self_node && scope.self_node != :self
238  
-            local(scope, 'self', scope.self_type)
239  
-          else
240  
-            real_self
  249
+        alias visitFloat visitFixnum
  250
+
  251
+        def visitSelf(node, expression)
  252
+          if expression
  253
+            set_position(node.position)
  254
+            scope = get_scope(node)
  255
+            if scope.self_node && scope.self_node != :self
  256
+              local(scope, 'self', scope.self_type)
  257
+            else
  258
+              real_self
  259
+            end
241 260
           end
242 261
         end
243 262
 
160  lib/mirah/jvm/compiler/java_source.rb
@@ -68,7 +68,7 @@ def define_method(node)
68 68
                 unless @method.type.nil? || @method.type.void?
69 69
                   self.return(ImplicitReturn.new(node.body))
70 70
                 else
71  
-                  node.body.compile(self, false) if node.body
  71
+                  visit(node.body, false) if node.body
72 72
                 end
73 73
               end
74 74
 
@@ -90,7 +90,7 @@ def define_optarg_chain(name, arg, return_type,
90 90
           @method.print "#{name}("
91 91
           @method.print args_for_opt.map(&:name).join(', ')
92 92
           @method.print ', 'if args_for_opt.size > 0
93  
-          arg.value.compile(self, true)
  93
+          visit(arg.value, true)
94 94
 
95 95
           # invoke the next one in the chain
96 96
           @method.print ");\n"
@@ -110,14 +110,14 @@ def constructor(node)
110 110
                 node.delegate_args.each_with_index do |arg, index|
111 111
                   method.print ', ' unless index == 0
112 112
                   raise "Invalid constructor argument #{arg}" unless arg.expr?(self)
113  
-                  arg.compile(self, true)
  113
+                  visit(arg, true)
114 114
                 end
115 115
                 method.puts ");"
116 116
               end
117 117
 
118 118
               prepare_binding(node) do
119 119
                 declare_locals(get_scope(node))
120  
-                node.body.compile(self, false) if node.body
  120
+                visit(node.body, false) if node.body
121 121
               end
122 122
               method.stop
123 123
             end
@@ -133,7 +133,7 @@ def prepare_binding(node)
133 133
             if node.respond_to? :arguments
134 134
               node.arguments.args.each do |param|
135 135
                 if scope.captured?(param.name)
136  
-                  captured_local_declare(scope, param.name, param.inferred_type)
  136
+                  captured_local_declare(scope, param.name, inferred_type(param))
137 137
                   @method.puts "$binding.#{param.name} = #{param.name};"
138 138
                 end
139 139
               end
@@ -149,19 +149,19 @@ def prepare_binding(node)
149 149
           end
150 150
         end
151 151
 
152  
-        def define_closure(class_def, expression)
  152
+        def visitClosureDefinition(class_def, expression)
153 153
           compiler = ClosureCompiler.new(@file, @type, self)
154  
-          compiler.define_class(class_def, expression)
  154
+          compiler.visitClassDefinition(class_def, expression)
155 155
         end
156 156
 
157  
-        def return(node)
  157
+        def visitReturn(node, expression)
158 158
           if @method.type.nil? || @method.type.void?
159 159
             @method.puts 'return;'
160 160
             return
161 161
           end
162 162
           if node.value.expr?(self)
163 163
             @method.print 'return '
164  
-            node.value.compile(self, true)
  164
+            visit(node.value, true)
165 165
             @method.puts ';'
166 166
           else
167 167
             store_value('return ', node.value)
@@ -171,7 +171,7 @@ def return(node)
171 171
         def _raise(node)
172 172
           if node.expr?(self)
173 173
             @method.print 'throw '
174  
-            node.compile(self, true)
  174
+            visit(node, true)
175 175
             @method.puts ';'
176 176
           else
177 177
             store_value('throw ', node)
@@ -183,7 +183,7 @@ def rescue(node, expression)
183 183
             if node.else_node.nil?
184 184
               maybe_store(node.body, expression) if node.body
185 185
             else
186  
-              node.body.compile(self, false) if node.body
  186
+              visit(node.body, false) if node.body
187 187
             end
188 188
           end
189 189
           node.clauses.each do |clause|
@@ -206,7 +206,7 @@ def ensure(node, expression)
206 206
             maybe_store(node.body, expression)
207 207
           end
208 208
           @method.block 'finally' do
209  
-            node.clause.compile(self, false)
  209
+            visit(node.clause, false)
210 210
           end
211 211
         end
212 212
 
@@ -226,9 +226,10 @@ def local(scope, name, type)
226 226
           @method.print name
227 227
         end
228 228
 
229  
-        def field(name, type, annotations, static_field)
230  
-          name = name[1..-1] if name =~ /^@/
231  
-          declare_field(name, type, annotations, static_field)
  229
+        def visitFieldAccess(field, expression)
  230
+          return unless expression
  231
+          name = field.name
  232
+          declare_field(name, inferred_type(field), field.annotations, field.isStatic)
232 233
           @method.print "#{this}.#{name}"
233 234
         end
234 235
 
@@ -268,7 +269,7 @@ def local_assign(scope, name, type, expression, value)
268 269
               end
269 270
             end
270 271
             @method.print "#{name} = "
271  
-            value.compile(self, true)
  272
+            visit(value, true)
272 273
             if simple && expression
273 274
               @method.print ')'
274 275
             else
@@ -276,7 +277,7 @@ def local_assign(scope, name, type, expression, value)
276 277
             end
277 278
           else
278 279
             @method.declare_local(type, name) do
279  
-              value.compile(self, true)
  280
+              visit(value, true)
280 281
             end
281 282
             if expression
282 283
               @method.puts "#{@lvalue}#{name};"
@@ -284,9 +285,8 @@ def local_assign(scope, name, type, expression, value)
284 285
           end
285 286
         end
286 287
 
287  
-        def field_declare(name, type, annotations)
288  
-          name = name[1..-1] if name =~ /^@/
289  
-          declare_field(name, type, annotations)
  288
+        def visitFieldDeclaration(decl, expression)
  289
+          declare_field(decl.name, inferred_type(decl), decl.annotations, decl.isStatic)
290 290
         end
291 291
 
292 292
         def local_declare(scope, name, type)
@@ -294,11 +294,11 @@ def local_declare(scope, name, type)
294 294
           declare_local(name, type)
295 295
         end
296 296
 
297  
-        def field_assign(name, type, expression, value, annotations, static_field)
298  
-          name = name[1..-1] if name =~ /^@/
299  
-          declare_field(name, type, annotations, static_field)
  297
+        def visitFieldAssign(field, expression)
  298
+          name = field.name
  299
+          declare_field(field.name, inferred_type(field), field.annotations, field.isStatic)
300 300
           lvalue = "#{@lvalue if expression}#{this}.#{name} = "
301  
-          store_value(lvalue, value)
  301
+          store_value(lvalue, field.value)
302 302
         end
303 303
 
304 304
         def captured_local_declare(scope, name, type)
@@ -314,7 +314,7 @@ def captured_local(scope, name, type)
314 314
         end
315 315
 
316 316
         def captured_local_assign(node, expression)
317  
-          scope, name, type = containing_scope(node), node.name, node.inferred_type
  317
+          scope, name, type = containing_scope(node), node.name, inferred_type(node)
318 318
           captured_local_declare(scope, name, type)
319 319
           lvalue = "#{@lvalue if expression}$binding.#{name} = "
320 320
           store_value(lvalue, node.value)
@@ -325,11 +325,11 @@ def store_value(lvalue, value)
325 325
             @method.puts "#{lvalue}#{value};"
326 326
           elsif value.expr?(self)
327 327
             @method.print lvalue
328  
-            value.compile(self, true)
  328
+            visit(value, true)
329 329
             @method.puts ';'
330 330
           else
331 331
             with :lvalue => lvalue do
332  
-              value.compile(self, true)
  332
+              visit(value, true)
333 333
             end
334 334
           end
335 335
         end
@@ -343,7 +343,7 @@ def maybe_store(value, expression)
343 343
           if expression
344 344
             store_value(@lvalue, value)
345 345
           else
346  
-            value.compile(self, false)
  346
+            visit(value, false)