mirah 0.1.2-java → 0.1.3-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/History.txt +225 -0
  3. data/Rakefile +108 -315
  4. data/TODO.md +100 -0
  5. data/bin/bundler +16 -0
  6. data/bin/rake +16 -0
  7. data/dist/mirahc.jar +0 -0
  8. data/examples/appengine/Readme +0 -1
  9. data/examples/literals.mirah +17 -0
  10. data/examples/macros/string_each_char.mirah +1 -1
  11. data/lib/mirah.rb +11 -21
  12. data/lib/mirah/transform/transformer.rb +1 -2
  13. data/lib/mirah/util/class_loader.rb +1 -1
  14. data/lib/mirah/util/logging.rb +0 -63
  15. data/lib/mirah/util/process_errors.rb +1 -0
  16. data/lib/mirah/version.rb +1 -1
  17. data/{examples/simple_class.mirah~ → test/artifacts/jar_test.rb} +7 -11
  18. data/{lib/mirah/commands.rb → test/artifacts/jruby_test.rb} +8 -5
  19. data/test/core/typer_test.rb +29 -11
  20. data/test/core/util/argument_processor_test.rb +24 -23
  21. data/test/core/util/class_loader_test.rb +7 -4
  22. data/test/core/util/{compilation_state_test.rb → jvm_version_test.rb} +20 -16
  23. data/test/fixtures/org/foo/ImplicitClassRetAnno.java +4 -0
  24. data/test/fixtures/org/foo/IntAnno.java +9 -0
  25. data/test/jvm/annotations_test.rb +11 -11
  26. data/test/jvm/blocks_test.rb +16 -12
  27. data/test/jvm/constructors_test.rb +8 -8
  28. data/test/jvm/enumerable_test.rb +48 -24
  29. data/test/jvm/generics_test.rb +3 -7
  30. data/test/jvm/import_test.rb +14 -0
  31. data/test/jvm/interface_test.rb +9 -24
  32. data/test/jvm/jvm_commands_test.rb +22 -4
  33. data/test/jvm/jvm_compiler_test.rb +124 -79
  34. data/test/jvm/list_extensions_test.rb +1 -1
  35. data/test/jvm/macros_test.rb +67 -14
  36. data/test/jvm/main_method_test.rb +1 -1
  37. data/test/jvm/new_backend_test_helper.rb +100 -3
  38. data/{lib/mirah/jvm/types/bitescript_ext.rb → test/jvm/static_fields_test.rb} +22 -21
  39. data/test/mirrors/base_type_test.rb +4 -3
  40. data/test/mirrors/bytecode_mirror_test.rb +35 -15
  41. data/test/mirrors/generics_test.rb +14 -5
  42. data/test/mirrors/member_test.rb +2 -1
  43. data/test/mirrors/method_lookup_test.rb +18 -6
  44. data/test/mirrors/mirrors_test.rb +87 -20
  45. data/test/mirrors/simple_async_mirror_loader_test.rb +7 -3
  46. data/test/mirrors/simple_mirror_loader_test.rb +5 -5
  47. data/test/test_helper.rb +25 -1
  48. metadata +18 -78
  49. data/bin/mirahp +0 -27
  50. data/bin/mirahp.cmd +0 -16
  51. data/examples/Fib.class +0 -0
  52. data/javalib/mirah-bootstrap.jar +0 -0
  53. data/javalib/mirah-builtins.jar +0 -0
  54. data/javalib/mirah-compiler.jar +0 -0
  55. data/javalib/mirah-mirrors.jar +0 -0
  56. data/javalib/mirah-newast-transitional.jar +0 -0
  57. data/javalib/mirah-parser.jar +0 -0
  58. data/javalib/mirah-util.jar +0 -0
  59. data/lib/mirah/ast.rb +0 -43
  60. data/lib/mirah/ast/scope.rb +0 -262
  61. data/lib/mirah/commands/base.rb +0 -59
  62. data/lib/mirah/commands/compile.rb +0 -39
  63. data/lib/mirah/commands/parse.rb +0 -36
  64. data/lib/mirah/commands/run.rb +0 -78
  65. data/lib/mirah/generator.rb +0 -150
  66. data/lib/mirah/jvm/compiler.rb +0 -50
  67. data/lib/mirah/jvm/compiler/base.rb +0 -421
  68. data/lib/mirah/jvm/compiler/jvm_bytecode.rb +0 -1194
  69. data/lib/mirah/jvm/method_lookup.rb +0 -307
  70. data/lib/mirah/jvm/types.rb +0 -45
  71. data/lib/mirah/jvm/types/array_type.rb +0 -60
  72. data/lib/mirah/jvm/types/ast_ext.rb +0 -31
  73. data/lib/mirah/jvm/types/basic_types.rb +0 -41
  74. data/lib/mirah/jvm/types/block_type.rb +0 -15
  75. data/lib/mirah/jvm/types/boolean.rb +0 -70
  76. data/lib/mirah/jvm/types/enumerable.rb +0 -80
  77. data/lib/mirah/jvm/types/extensions.rb +0 -110
  78. data/lib/mirah/jvm/types/factory.rb +0 -830
  79. data/lib/mirah/jvm/types/floats.rb +0 -99
  80. data/lib/mirah/jvm/types/generic_type.rb +0 -72
  81. data/lib/mirah/jvm/types/implicit_nil_type.rb +0 -29
  82. data/lib/mirah/jvm/types/integers.rb +0 -131
  83. data/lib/mirah/jvm/types/interface_definition.rb +0 -20
  84. data/lib/mirah/jvm/types/intrinsics.rb +0 -385
  85. data/lib/mirah/jvm/types/literals.rb +0 -89
  86. data/lib/mirah/jvm/types/meta_type.rb +0 -54
  87. data/lib/mirah/jvm/types/methods.rb +0 -946
  88. data/lib/mirah/jvm/types/null_type.rb +0 -39
  89. data/lib/mirah/jvm/types/number.rb +0 -184
  90. data/lib/mirah/jvm/types/primitive_type.rb +0 -76
  91. data/lib/mirah/jvm/types/source_mirror.rb +0 -274
  92. data/lib/mirah/jvm/types/type.rb +0 -311
  93. data/lib/mirah/jvm/types/type_definition.rb +0 -72
  94. data/lib/mirah/jvm/types/void_type.rb +0 -19
  95. data/lib/mirah/util/compilation_state.rb +0 -60
  96. data/test/core/commands_test.rb +0 -89
  97. data/test/core/generator_test.rb +0 -26
  98. data/test/fixtures/org/foo/LowerCaseInnerClass$inner.class +0 -0
  99. data/test/fixtures/org/foo/LowerCaseInnerClass.class +0 -0
  100. data/test/jvm/bytecode_test_helper.rb +0 -193
  101. data/test/jvm/factory_test.rb +0 -28
  102. data/test/jvm/java_typer_test.rb +0 -283
@@ -1,36 +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
- require 'mirah/parser'
17
-
18
- module Mirah
19
- module Commands
20
- class Parse < Base
21
- def execute
22
- execute_base do
23
- parser = Mirah::Parser.new(@state, nil, false)
24
-
25
- parser.parse_from_args(args).each do |ast|
26
- puts parser.format_ast(ast)
27
- end
28
- end
29
- end
30
-
31
- def command_name
32
- :parse
33
- end
34
- end
35
- end
36
- end
@@ -1,78 +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
- require 'mirah/generator'
17
- require 'mirah/util/class_loader'
18
-
19
- module Mirah
20
- module Commands
21
- class Run < Base
22
- def execute
23
- execute_base do
24
- class_map = generate_classes
25
- $CLASSPATH << Mirah::Env.decode_paths(@state.classpath) if @state.classpath
26
- class_loader = load_classes class_map
27
-
28
- main = find_main class_map, class_loader
29
-
30
- run_main(main)
31
- end
32
- end
33
-
34
- def command_name
35
- :run
36
- end
37
-
38
- private
39
-
40
- def load_classes(class_map)
41
- Mirah::Util::ClassLoader.new(JRuby.runtime.jruby_class_loader, class_map)
42
- end
43
-
44
- def find_main class_map, class_loader
45
- # TODO: using first main; find correct one?
46
- class_map.keys.each do |name|
47
- cls = class_loader.load_class(name)
48
- main = cls.get_method("main", java::lang::String[].java_class)
49
- return main if main
50
- end
51
- nil
52
- end
53
-
54
- def run_main(main)
55
- if main
56
- begin
57
- main.invoke(nil, [args.to_java(:string)].to_java)
58
- rescue java.lang.Exception => e
59
- e = e.cause if e.cause
60
- raise e
61
- end
62
- else
63
- puts "No main found" unless @state.version_printed || @state.help_printed
64
- end
65
- end
66
-
67
- def generate_classes
68
- # generate all bytes for all classes
69
- generator = Mirah::Generator.new(@state, @state.compiler_class, false, @state.verbose)
70
- class_map = {}
71
- generator.generate(args).each do |result|
72
- class_map[result.classname.gsub(/\//, '.')] = Mirah::Util::ClassLoader.binary_string result.bytes
73
- end
74
- class_map
75
- end
76
- end
77
- end
78
- end
@@ -1,150 +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
- require 'mirah/util/process_errors'
16
- require 'mirah/util/logging'
17
-
18
- module Mirah
19
- class Generator
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
-
26
- def initialize(state, compiler_class, logging, verbose)
27
- @state = state
28
-
29
- # TODO untie this from the jvm backend (nh)
30
- if state.type_system
31
- # Using new type system
32
- @scoper = SimpleScoper.new do |scoper, node|
33
- scope = Java::OrgMirahJvmMirrors::JVMScope.new(scoper)
34
- scope.context_set(node)
35
- scope
36
- end
37
- type_system = state.type_system
38
- else
39
- @scoper = SimpleScoper.new {|scoper, node| Mirah::AST::StaticScope.new(node, scoper)}
40
- type_system = Mirah::JVM::Types::TypeFactory.new
41
- type_system.classpath = state.classpath if state.classpath
42
- type_system.bootclasspath = state.bootclasspath
43
- end
44
-
45
- @typer = Mirah::Typer::Typer.new(type_system, @scoper, self, nil)
46
- @parser = Mirah::Parser.new(state, @typer, logging)
47
- @compiler = Mirah::Compiler::ASTCompiler.new(state, compiler_class, logging)
48
- @extension_compiler = Mirah::Compiler::ASTCompiler.new(state, compiler_class, logging)
49
- if type_system.respond_to?(:maybe_initialize_builtins)
50
- type_system.maybe_initialize_builtins(@typer.macro_compiler)
51
- end
52
- @logging = logging
53
- @verbose = verbose
54
- end
55
-
56
- attr_accessor :parser, :compiler, :typer, :logging, :verbose
57
-
58
- def generate(arguments)
59
- # collect all ASTs from all files
60
- top_nodes = parser.parse_from_args(arguments)
61
-
62
- # enter all ASTs into inference engine
63
- puts "Inferring types..." if logging
64
- scoper, typer = infer_asts(top_nodes)
65
- do_transforms top_nodes
66
- # compile each AST in turn
67
- compiler_results = compiler.compile_asts(top_nodes, scoper, typer)
68
-
69
- puts "Done!" if logging
70
-
71
- compiler_results
72
- end
73
-
74
- def do_transforms nodes
75
- log("Starting Transform")
76
-
77
- java_import 'org.mirah.jvm.compiler.ClosureTransformer' rescue puts $!
78
- java_import 'org.mirah.util.Context' rescue puts $!
79
- #java_import 'org.mirah.typer.Typer'
80
- #java_import 'org.mirah.macros.Compiler'
81
- transformer = ClosureTransformer.new(Context.new.tap{|c|c.add(Java::org.mirah.typer::Typer, @typer) }) rescue nil
82
- if transformer
83
- nodes.each{|n| n.accept transformer, nil } # rescue log("transformer exception", $!.cause)
84
- log("POST Transform")
85
- log_types nodes
86
- else
87
- log "No transformer, skipping"
88
- end
89
- end
90
-
91
- def infer_asts(nodes, should_raise=false)
92
- log_and_reraise "Caught exception during type inference" do
93
- nodes.each {|ast| @typer.infer(ast, false) }
94
- if should_raise
95
- error_handler = lambda do |errors|
96
- message, position = errors[0].message[0].to_a
97
- raise Mirah::MirahError.new(message, position)
98
- end
99
- end
100
- process_inference_errors(@typer, nodes, &error_handler)
101
- end
102
- [@scoper, @typer]
103
- ensure
104
- log_types(nodes)
105
- end
106
-
107
- def log_and_reraise message
108
- yield
109
- rescue NativeException => ex
110
- log(message, ex.cause)
111
- raise ex
112
- end
113
-
114
- def log_types(nodes)
115
- if self.logging?
116
- buf = java.io.ByteArrayOutputStream.new
117
- ps = java.io.PrintStream.new(buf)
118
- printer = TypePrinter.new(@typer, ps)
119
- nodes.each {|ast| printer.scan(ast, nil)}
120
- ps.close()
121
- log("Inferred types:\n{0}", java.lang.String.new(buf.toByteArray))
122
- end
123
-
124
- end
125
-
126
- def compileAndLoadExtension(ast)
127
- log_types([ast])
128
- process_inference_errors(@typer, [ast])
129
- results = @extension_compiler.compile_asts([ast], @scoper, @typer)
130
- class_map = {}
131
- first_class_name = nil
132
- results.each do |result|
133
- classname = result.classname.gsub(/\//, '.')
134
- first_class_name ||= classname if classname.include?('$Extension')
135
- class_map[classname] = Mirah::Util::ClassLoader.binary_string result.bytes
136
- if @state.save_extensions
137
- filename = "#{@state.destination}#{result.filename}"
138
- FileUtils.mkdir_p(File.dirname(filename))
139
- File.open(filename, 'wb') {|f| f.write(result.bytes)}
140
- end
141
- end
142
- dcl = Mirah::Util::ClassLoader.new(JRuby.runtime.jruby_class_loader, class_map)
143
- dcl.load_class(first_class_name)
144
- end
145
-
146
- def logExtensionAst(ast)
147
- log("Extension ast:\n#{parser.format_ast(ast)}")
148
- end
149
- end
150
- end
@@ -1,50 +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
- require 'mirah'
17
- require 'mirah/jvm/compiler/base'
18
- require 'mirah/jvm/method_lookup'
19
- require 'mirah/jvm/types'
20
- require 'bitescript'
21
- require 'mirah/jvm/compiler/jvm_bytecode'
22
- require 'mirah/transform/ast_ext'
23
-
24
- module Mirah
25
- module AST
26
- class FunctionalCall
27
- attr_accessor :target
28
- end
29
-
30
- class Super
31
- attr_accessor :target
32
- end
33
- end
34
- end
35
-
36
- module Mirah
37
- module JVM
38
- module Compiler
39
- begin
40
- class Backend < Java::OrgMirahJvmCompiler::Backend
41
- def initialize(config, scoper, typer)
42
- super(typer)
43
- end
44
- end
45
- rescue NameError
46
- puts "Unable to load new Backend"
47
- end
48
- end
49
- end
50
- end
@@ -1,421 +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 JVM
18
- module Compiler
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
25
- attr_accessor :filename, :method, :static, :class
26
- include Mirah::Logging::Logged
27
-
28
- class CompilationError < Mirah::NodeError
29
- end
30
-
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
38
- @jump_scope = []
39
- @bindings = Hash.new {|h, type| h[type] = type.define(@file)}
40
- @captured_locals = Hash.new {|h, binding| h[binding] = {}}
41
- @self_scope = nil
42
- @scoper = typer.scoper
43
- @typer = typer
44
- end
45
-
46
- def target_jvm_version
47
- @config.target_jvm_version
48
- end
49
-
50
- def supports_invokedynamic?
51
- @config.supports_invokedynamic?
52
- end
53
-
54
- def defaultNode(node, expression)
55
- raise ArgumentError, "Can't compile node #{node}"
56
- end
57
-
58
- def visit(node, expression)
59
- begin
60
- node.accept(self, expression)
61
- rescue Exception => ex
62
- raise Mirah::InternalCompilerError.wrap(ex, node)
63
- end
64
- end
65
-
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
94
-
95
- def toplevel_class
96
- @class = @type.define(@file)
97
- end
98
-
99
- def generate
100
- log "Generating #{output_type}..."
101
- @file.generate do |filename, builder|
102
- log " #{builder.class_name}"
103
- if block_given?
104
- yield filename, builder
105
- else
106
- File.open(filename, 'wb') {|f| f.write(builder.generate)}
107
- end
108
- end
109
- log "...done!"
110
- end
111
-
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)
158
- @static = true
159
- @filename = File.basename(script.position.source.name)
160
- classname = Mirah::JVM::Compiler::JVMBytecode.classname_from_filename(@filename)
161
- @type = @typer.type_system.type(get_scope(script), classname)
162
- @file = file_builder(@filename)
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
168
- @class = @type.define(@file)
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
182
-
183
- finish_main
184
- @method.stop
185
- end
186
- log "Main method complete!"
187
- else
188
- visit(body, false)
189
- end
190
- @class.stop
191
- else
192
- visit(body, false)
193
- end
194
- end
195
-
196
- def visitNoop(node, expression)
197
- end
198
-
199
- def begin_main; end
200
- def finish_main; end
201
-
202
- # arg_types must be an Array
203
- def create_method_builder(name, node, static, exceptions, return_type, arg_types)
204
- return_type = nil if return_type.name == ':unreachable'
205
- visibility = :public # TODO
206
- flags = BiteScript::ASM::Opcodes::ACC_PUBLIC
207
- flags |= BiteScript::ASM::Opcodes::ACC_STATIC if static
208
- flags |= BiteScript::ASM::Opcodes::ACC_ABSTRACT if node.annotated_abstract?
209
- @class.method(flags, name.to_s, [return_type, *arg_types], exceptions)
210
- end
211
-
212
- def base_define_method(node)
213
- name = node.name.identifier.sub(/=$/, '_set')
214
- args = visit(node.arguments, true)
215
- is_static = self.static || node.kind_of?(StaticMethodDefinition)
216
- if name == "initialize" && is_static
217
- name = "<clinit>"
218
- end
219
- arg_types = args.map { |arg| inferred_type(arg) }
220
- return_type = inferred_type(node).return_type
221
- exceptions = [] # TODO
222
-
223
- with :static => is_static, :current_scope => introduced_scope(node) do
224
- method = create_method_builder(name, node, @static, exceptions,
225
- return_type, arg_types)
226
- annotate(method, node.annotations)
227
- yield method, arg_types
228
- end
229
-
230
- arg_types_for_opt = []
231
- args_for_opt = []
232
- if args
233
- args.each do |arg|
234
- if AST::OptionalArgument === arg
235
- new_args = arg_types_for_opt
236
- method = create_method_builder(name, node, @static, exceptions,
237
- return_type, new_args)
238
- with :method => method do
239
- log "Starting new method #{name}(#{arg_types_for_opt})"
240
-
241
- annotate(method, node.annotations)
242
- @method.start
243
-
244
- define_optarg_chain(name, arg,
245
- return_type,
246
- args_for_opt,
247
- arg_types_for_opt)
248
-
249
- @method.stop
250
- end
251
- end
252
- arg_types_for_opt << inferred_type(arg)
253
- args_for_opt << arg
254
- end
255
- end
256
- end
257
-
258
- def visitConstructorDefinition(node, expression)
259
- args = visit(node.arguments, true)
260
- arg_types = args.map { |arg| inferred_type(arg) }
261
- exceptions = [] # node.signature[:throws]
262
- visibility = :public # node.visibility
263
- method = @class.build_constructor(visibility, exceptions, *arg_types)
264
- annotate(method, node.annotations)
265
- with :current_scope => introduced_scope(node) do
266
- yield(method, args)
267
- end
268
- end
269
-
270
- def visitClassDefinition(class_def, expression)
271
- log "Compiling class #{class_def.name.identifier}"
272
- with(:type => inferred_type(class_def),
273
- :class => inferred_type(class_def).define(@file),
274
- :static => false) do
275
- annotate(@class, class_def.annotations)
276
- visit(class_def.body, false) if class_def.body
277
- @class.stop
278
- end
279
- end
280
-
281
- def visitArguments(args, expression)
282
- result = []
283
- args.required.each {|arg| result << arg}
284
- args.optional.each {|arg| result << arg}
285
- result << args.rest if args.rest
286
- args.required2.each {|arg| result << arg}
287
- result << args.block if args.block
288
- result
289
- end
290
-
291
- def visitStaticMethodDefinition(mdef, expression)
292
- visitMethodDefinition(mdef, expression)
293
- end
294
-
295
- def visitNodeList(body, expression)
296
- saved_self = @self_scope
297
- new_scope = introduced_scope(body)
298
- if new_scope
299
- declare_locals(new_scope)
300
- if new_scope != @self_scope
301
- if new_scope.self_node && new_scope.self_node != :self
302
- # FIXME This is a horrible hack!
303
- # Instead we should eliminate unused self's.
304
- unless new_scope.self_type.name == 'mirah.impl.Builtin'
305
- local_assign(
306
- new_scope, 'self', new_scope.self_type, false, new_scope.self_node)
307
- end
308
- end
309
- @self_scope = new_scope
310
- end
311
- end
312
- # all except the last element in a body of code is treated as a statement
313
- i, last = 0, body.size - 1
314
- while i < last
315
- visit(body.get(i), false)
316
- i += 1
317
- end
318
- if last >= 0
319
- yield body.get(last)
320
- else
321
- yield nil
322
- end
323
- @self_scope = saved_self
324
- end
325
-
326
- def visitClassAppendSelf(node, expression)
327
- with :static => true, :current_scope => introduced_scope(node) do
328
- visit(node.body, expression)
329
- end
330
- end
331
-
332
- def visitPackage(node, expression)
333
- visit(node.body, expression) if node.body
334
- end
335
-
336
- def scoped_body(scope, expression)
337
- body(scope, expression)
338
- end
339
-
340
- def scoped_local_name(name, scope=nil)
341
- if scope.nil? || scope == @current_scope
342
- name
343
- else
344
- "#{name}$#{scope.object_id}"
345
- end
346
- end
347
-
348
- def visitImport(node, expression)
349
- end
350
-
351
- def visitFixnum(node, expression)
352
- if expression
353
- inferred_type(node).literal(method, node.value)
354
- end
355
- end
356
-
357
- def visitCharLiteral(node, expression)
358
- if expression
359
- inferred_type(node).literal(method, node.value)
360
- end
361
- end
362
-
363
- alias visitFloat visitFixnum
364
-
365
- def visitSelf(node, expression)
366
- if expression
367
- set_position(node.position)
368
- scope = get_scope(node)
369
- if scope.self_node && scope.self_node != :self
370
- local(scope, 'self', scope.self_type)
371
- else
372
- real_self
373
- end
374
- end
375
- end
376
-
377
- def visitImplicitSelf(node, expression)
378
- visitSelf(node, expression)
379
- end
380
-
381
- def visitUnquote(node, expression)
382
- body = node.nodes
383
- i, last = 0, body.size - 1
384
- while i < last
385
- visit(body.get(i), false)
386
- i += 1
387
- end
388
- if last >= 0
389
- visit(body.get(last), expression)
390
- else
391
- visitImplicitNil(node, expression)
392
- end
393
- end
394
-
395
- def get_binding(type)
396
- @bindings[type]
397
- end
398
-
399
- def declared_captures(binding=nil)
400
- @captured_locals[binding || @binding]
401
- end
402
-
403
- def with(vars)
404
- orig_values = {}
405
- begin
406
- vars.each do |name, new_value|
407
- name = "@#{name}"
408
- orig_values[name] = instance_variable_get name
409
- instance_variable_set name, new_value
410
- end
411
- yield
412
- ensure
413
- orig_values.each do |name, value|
414
- instance_variable_set name, value
415
- end
416
- end
417
- end
418
- end
419
- end
420
- end
421
- end