mirah 0.0.12-java → 0.1.0-java
Sign up to get free protection for your applications and to get access to all the features.
- 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
|