mirah 0.0.12-java → 0.1.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +372 -0
- data/README.txt +4 -5
- data/Rakefile +178 -55
- data/examples/appengine/Readme +3 -3
- data/examples/appengine/src/org/mirah/MirahApp.mirah +1 -1
- data/examples/appengine/src/org/mirah/list.dhtml +1 -1
- data/examples/bintrees.mirah +1 -1
- data/examples/edb.mirah +1 -1
- data/examples/fib.mirah +1 -1
- data/examples/interfaces.mirah +1 -1
- data/examples/macros/{string-each-char.mirah → string_each_char.mirah} +4 -5
- data/examples/maven/README.txt +1 -1
- data/examples/maven/src/main/mirah/hello_mirah.mirah +1 -1
- data/examples/plugins/appengine/Rakefile +1 -1
- data/examples/plugins/appengine/src/com/google/appengine/ext/duby/db/MetaModel.mirah +1 -1
- data/examples/plugins/appengine/src/com/google/appengine/ext/duby/db/Model.duby +1 -1
- data/examples/plugins/appengine/test/com/google/appengine/ext/duby/db/ModelTest.duby +1 -1
- data/examples/rosettacode/100-doors.mirah +6 -6
- data/examples/rosettacode/README.txt +3 -3
- data/examples/rosettacode/boolean-values.mirah +1 -1
- data/examples/rosettacode/comments.mirah +1 -1
- data/examples/rosettacode/count-occurrences-of-a-substring.mirah +1 -1
- data/examples/rosettacode/factorial.mirah +1 -1
- data/examples/rosettacode/fibonacci.mirah +1 -1
- data/examples/rosettacode/fizz-buzz.mirah +2 -2
- data/examples/rosettacode/flatten-a-list.mirah +4 -4
- data/examples/rosettacode/guess-the-number.mirah +2 -2
- data/examples/rosettacode/hamming-numbers.mirah +4 -4
- data/examples/rosettacode/is-string-numeric.mirah +22 -22
- data/examples/rosettacode/palindrome.mirah +2 -2
- data/examples/rosettacode/random-numbers.mirah +1 -1
- data/examples/rosettacode/repeat-a-string.mirah +1 -1
- data/examples/rosettacode/reverse-a-string.mirah +1 -1
- data/examples/rosettacode/rot-13.mirah +5 -5
- data/examples/rosettacode/secure-temporary-file.mirah +2 -2
- data/examples/rosettacode/sleep.mirah +1 -1
- data/examples/rosettacode/string-length.mirah +5 -5
- data/examples/swing.mirah +1 -1
- data/examples/test.edb +1 -1
- data/javalib/mirah-bootstrap.jar +0 -0
- data/javalib/mirah-builtins.jar +0 -0
- data/javalib/mirah-parser.jar +0 -0
- data/javalib/mirah-util.jar +0 -0
- data/lib/duby.rb +1 -1
- data/lib/mirah.rb +50 -28
- data/lib/mirah/ast.rb +15 -605
- data/lib/mirah/ast/scope.rb +98 -69
- data/lib/mirah/commands.rb +1 -1
- data/lib/mirah/commands/base.rb +7 -7
- data/lib/mirah/commands/compile.rb +3 -3
- data/lib/mirah/commands/parse.rb +7 -5
- data/lib/mirah/commands/run.rb +12 -19
- data/lib/mirah/compiler.rb +15 -23
- data/lib/mirah/errors.rb +16 -1
- data/lib/mirah/generator.rb +79 -39
- data/lib/mirah/jvm/compiler.rb +1 -19
- data/lib/mirah/jvm/compiler/base.rb +233 -90
- data/lib/mirah/jvm/compiler/jvm_bytecode.rb +675 -363
- data/lib/mirah/jvm/method_lookup.rb +134 -65
- data/lib/mirah/jvm/typer.rb +10 -5
- data/lib/mirah/jvm/types.rb +10 -2
- data/lib/mirah/jvm/types/array_type.rb +10 -12
- data/lib/mirah/{compiler/type.rb → jvm/types/ast_ext.rb} +12 -8
- data/lib/mirah/jvm/types/basic_types.rb +26 -33
- data/lib/mirah/jvm/types/bitescript_ext.rb +1 -1
- data/lib/mirah/jvm/types/block_type.rb +15 -0
- data/lib/mirah/jvm/types/boolean.rb +8 -4
- data/lib/mirah/jvm/types/dynamic_type.rb +12 -13
- data/lib/mirah/jvm/types/enumerable.rb +7 -7
- data/lib/mirah/jvm/types/extensions.rb +11 -6
- data/lib/mirah/jvm/types/factory.rb +624 -94
- data/lib/mirah/jvm/types/floats.rb +21 -15
- data/lib/mirah/jvm/types/generic_type.rb +72 -0
- data/lib/mirah/jvm/types/implicit_nil_type.rb +29 -0
- data/lib/mirah/jvm/types/integers.rb +26 -71
- data/lib/mirah/jvm/types/interface_definition.rb +3 -3
- data/lib/mirah/jvm/types/intrinsics.rb +203 -168
- data/lib/mirah/jvm/types/literals.rb +6 -6
- data/lib/mirah/jvm/types/meta_type.rb +13 -4
- data/lib/mirah/jvm/types/methods.rb +281 -93
- data/lib/mirah/jvm/types/null_type.rb +17 -5
- data/lib/mirah/jvm/types/number.rb +10 -7
- data/lib/mirah/jvm/types/primitive_type.rb +17 -6
- data/lib/mirah/jvm/types/source_mirror.rb +12 -7
- data/lib/mirah/jvm/types/type.rb +107 -23
- data/lib/mirah/jvm/types/type_definition.rb +25 -10
- data/lib/mirah/jvm/types/unreachable_type.rb +1 -1
- data/lib/mirah/jvm/types/void_type.rb +3 -3
- data/lib/mirah/parser.rb +154 -16
- data/lib/mirah/plugin/edb.rb +1 -1
- data/lib/mirah/transform.rb +1 -2
- data/lib/mirah/transform/ast_ext.rb +24 -43
- data/lib/mirah/transform/transformer.rb +29 -224
- data/lib/mirah/typer.rb +2 -16
- data/lib/mirah/util/argument_processor.rb +25 -10
- data/lib/mirah/util/class_loader.rb +1 -1
- data/lib/mirah/util/compilation_state.rb +16 -17
- data/lib/mirah/util/delegate.rb +2 -2
- data/lib/mirah/util/logging.rb +110 -0
- data/lib/mirah/util/process_errors.rb +69 -11
- data/lib/mirah/version.rb +1 -1
- data/test/core/commands_test.rb +6 -24
- data/test/core/env_test.rb +5 -5
- data/{lib/mirah/jvm/source_generator/typer.rb → test/core/generator_test.rb} +9 -9
- data/test/core/typer_test.rb +196 -158
- data/test/core/util/argument_processor_test.rb +10 -10
- data/test/core/util/class_loader_test.rb +6 -5
- data/test/fixtures/org/foo/LowerCaseInnerClass$inner.class +0 -0
- data/test/fixtures/org/foo/LowerCaseInnerClass.class +0 -0
- data/test/fixtures/org/foo/LowerCaseInnerClass.java +7 -0
- data/test/jvm/annotations_test.rb +5 -5
- data/test/jvm/blocks_test.rb +140 -88
- data/test/jvm/bytecode_test_helper.rb +112 -94
- data/test/jvm/cast_test.rb +162 -0
- data/test/jvm/constructors_test.rb +18 -8
- data/test/jvm/enumerable_test.rb +77 -44
- data/test/jvm/example_test.rb +53 -0
- data/test/jvm/factory_test.rb +7 -1
- data/test/jvm/generics_test.rb +57 -0
- data/test/jvm/hash_test.rb +106 -0
- data/test/jvm/import_test.rb +81 -0
- data/test/jvm/interface_test.rb +73 -0
- data/test/jvm/java_typer_test.rb +92 -66
- data/{lib/mirah/typer/base.rb → test/jvm/jvm_commands_test.rb} +6 -10
- data/test/jvm/jvm_compiler_test.rb +170 -604
- data/test/jvm/list_extensions_test.rb +23 -0
- data/test/jvm/macros_test.rb +197 -32
- data/test/jvm/main_method_test.rb +4 -4
- data/test/jvm/numeric_extensions_test.rb +13 -0
- data/test/jvm/rescue_test.rb +73 -16
- data/test/jvm/varargs_test.rb +65 -0
- data/test/test_helper.rb +1 -2
- metadata +234 -251
- data/examples/SortClosure$__xform_tmp_1.class +0 -0
- data/examples/SortClosure$__xform_tmp_2.class +0 -0
- data/examples/SortClosure.class +0 -0
- data/examples/macros/StringEachChar$Extension1.class +0 -0
- data/lib/mirah/ast/call.rb +0 -345
- data/lib/mirah/ast/class.rb +0 -359
- data/lib/mirah/ast/flow.rb +0 -381
- data/lib/mirah/ast/intrinsics.rb +0 -563
- data/lib/mirah/ast/literal.rb +0 -178
- data/lib/mirah/ast/local.rb +0 -112
- data/lib/mirah/ast/method.rb +0 -408
- data/lib/mirah/ast/structure.rb +0 -387
- data/lib/mirah/ast/type.rb +0 -146
- data/lib/mirah/commands/base.rb~ +0 -57
- data/lib/mirah/compiler/call.rb +0 -45
- data/lib/mirah/compiler/class.rb +0 -81
- data/lib/mirah/compiler/flow.rb +0 -109
- data/lib/mirah/compiler/literal.rb +0 -130
- data/lib/mirah/compiler/local.rb +0 -59
- data/lib/mirah/compiler/method.rb +0 -44
- data/lib/mirah/compiler/structure.rb +0 -65
- data/lib/mirah/jvm/compiler/java_source.rb +0 -787
- data/lib/mirah/jvm/method_lookup.rb~ +0 -247
- data/lib/mirah/jvm/source_generator/builder.rb +0 -468
- data/lib/mirah/jvm/source_generator/loops.rb +0 -131
- data/lib/mirah/jvm/source_generator/precompile.rb +0 -210
- data/lib/mirah/plugin/gwt.rb +0 -189
- data/lib/mirah/plugin/java.rb +0 -70
- data/lib/mirah/transform/error.rb +0 -13
- data/lib/mirah/transform/helper.rb +0 -765
- data/lib/mirah/typer/simple.rb +0 -384
- data/lib/mirah/version.rb~ +0 -18
- data/test/core/ast_test.rb +0 -382
- data/test/core/compilation_test.rb +0 -130
- data/test/core/macros_test.rb +0 -61
- data/test/jvm/javac_test_helper.rb +0 -89
- data/test/jvm/jvm_compiler_test.rb~ +0 -2181
- 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
|
data/lib/mirah/generator.rb
CHANGED
|
@@ -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
|
-
@
|
|
22
|
-
@
|
|
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.
|
|
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
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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
|
data/lib/mirah/jvm/compiler.rb
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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
|
|
33
|
-
|
|
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
|
|
58
|
+
def visit(node, expression)
|
|
37
59
|
begin
|
|
38
|
-
|
|
60
|
+
node.accept(self, expression)
|
|
39
61
|
rescue Exception => ex
|
|
40
|
-
raise Mirah::InternalCompilerError.wrap(ex,
|
|
62
|
+
raise Mirah::InternalCompilerError.wrap(ex, node)
|
|
41
63
|
end
|
|
42
|
-
log "Compilation successful!"
|
|
43
64
|
end
|
|
44
65
|
|
|
45
|
-
def
|
|
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
|
-
|
|
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.
|
|
159
|
+
@filename = File.basename(script.position.source.name)
|
|
67
160
|
classname = Mirah::JVM::Compiler::JVMBytecode.classname_from_filename(@filename)
|
|
68
|
-
@type =
|
|
161
|
+
@type = @typer.type_system.type(get_scope(script), classname)
|
|
69
162
|
@file = file_builder(@filename)
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
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
|
-
|
|
84
|
-
|
|
183
|
+
finish_main
|
|
184
|
+
@method.stop
|
|
85
185
|
end
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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
|
-
|
|
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
|
-
|
|
104
|
-
|
|
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
|
|
108
|
-
name
|
|
109
|
-
|
|
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
|
-
|
|
113
|
-
|
|
114
|
-
|
|
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 =>
|
|
222
|
+
with :static => is_static, :current_scope => introduced_scope(node) do
|
|
122
223
|
method = create_method_builder(name, node, @static, exceptions,
|
|
123
|
-
|
|
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 =
|
|
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
|
|
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
|
|
161
|
-
args = node.arguments
|
|
162
|
-
arg_types =
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
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
|
|
264
|
+
with :current_scope => introduced_scope(node) do
|
|
171
265
|
yield(method, args)
|
|
172
266
|
end
|
|
173
267
|
end
|
|
174
268
|
|
|
175
|
-
def
|
|
176
|
-
|
|
177
|
-
:
|
|
178
|
-
|
|
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
|
|
275
|
+
visit(class_def.body, false) if class_def.body
|
|
181
276
|
@class.stop
|
|
182
277
|
end
|
|
183
278
|
end
|
|
184
279
|
|
|
185
|
-
def
|
|
186
|
-
|
|
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
|
|
294
|
+
def visitNodeList(body, expression)
|
|
190
295
|
saved_self = @self_scope
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
declare_locals(
|
|
194
|
-
if
|
|
195
|
-
if
|
|
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
|
|
303
|
+
unless new_scope.self_type.name == 'mirah.impl.Builtin'
|
|
199
304
|
local_assign(
|
|
200
|
-
|
|
305
|
+
new_scope, 'self', new_scope.self_type, false, new_scope.self_node)
|
|
201
306
|
end
|
|
202
307
|
end
|
|
203
|
-
@self_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.
|
|
312
|
+
i, last = 0, body.size - 1
|
|
208
313
|
while i < last
|
|
209
|
-
body.
|
|
314
|
+
visit(body.get(i), false)
|
|
210
315
|
i += 1
|
|
211
316
|
end
|
|
212
|
-
|
|
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
|
|
347
|
+
def visitImport(node, expression)
|
|
229
348
|
end
|
|
230
349
|
|
|
231
|
-
def
|
|
232
|
-
|
|
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
|
|
237
|
-
|
|
238
|
-
|
|
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
|
-
|
|
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
|