mirah 0.0.7-java → 0.0.8-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 +181 -0
- data/README.txt +6 -10
- data/Rakefile +86 -9
- data/bin/mirah +2 -0
- data/bin/mirahc +2 -0
- data/bin/mirahp +2 -0
- data/{bin/dubyp → examples/interfaces.mirah} +16 -9
- data/examples/macros/square.mirah +12 -0
- data/examples/macros/square_int.mirah +12 -0
- data/examples/macros/string-each-char.mirah +14 -0
- data/examples/maven/README.txt +2 -0
- data/examples/maven/pom.xml +23 -0
- data/examples/maven/src/main/mirah/hello_mirah.mirah +9 -0
- data/examples/rosettacode/100-doors.mirah +44 -0
- data/examples/rosettacode/99-bottles-of-beer.mirah +13 -0
- data/examples/rosettacode/README.txt +9 -0
- data/examples/rosettacode/boolean-values.mirah +29 -0
- data/examples/rosettacode/comments.mirah +2 -0
- data/examples/rosettacode/copy-a-string.mirah +10 -0
- data/examples/rosettacode/count-occurrences-of-a-substring.mirah +40 -0
- data/examples/rosettacode/create-a-file.mirah +6 -0
- data/examples/rosettacode/empty-string.mirah +9 -0
- data/examples/rosettacode/factorial.mirah +10 -0
- data/examples/rosettacode/fibonacci.mirah +21 -0
- data/examples/rosettacode/file-size.mirah +5 -0
- data/examples/rosettacode/fizz-buzz.mirah +21 -0
- data/examples/rosettacode/flatten-a-list.mirah +24 -0
- data/examples/rosettacode/guess-the-number.mirah +21 -0
- data/examples/rosettacode/is-string-numeric.mirah +127 -0
- data/examples/rosettacode/palindrome.mirah +14 -0
- data/examples/rosettacode/repeat-a-string.mirah +9 -0
- data/examples/rosettacode/reverse-a-string.mirah +6 -0
- data/examples/rosettacode/rot-13.mirah +20 -0
- data/examples/rosettacode/user-input.mirah +4 -0
- data/examples/sort_closure.mirah +1 -1
- data/javalib/dynalink-0.2.jar +0 -0
- data/javalib/mirah-bootstrap.jar +0 -0
- data/lib/mirah.rb +7 -16
- data/lib/mirah/ast.rb +22 -92
- data/lib/mirah/ast/call.rb +41 -9
- data/lib/mirah/ast/class.rb +34 -6
- data/lib/mirah/ast/flow.rb +17 -5
- data/lib/mirah/ast/intrinsics.rb +50 -8
- data/lib/mirah/ast/literal.rb +7 -0
- data/lib/mirah/ast/local.rb +9 -1
- data/lib/mirah/ast/method.rb +21 -8
- data/lib/mirah/ast/scope.rb +1 -1
- data/lib/mirah/ast/structure.rb +81 -15
- data/lib/mirah/ast/type.rb +4 -0
- data/{bin/dubyc → lib/mirah/commands.rb} +4 -11
- data/lib/mirah/commands/base.rb +54 -0
- data/lib/mirah/commands/compile.rb +39 -0
- data/{examples/wiki/Rakefile → lib/mirah/commands/parse.rb} +18 -17
- data/lib/mirah/commands/run.rb +73 -0
- data/lib/mirah/compiler.rb +37 -417
- data/lib/mirah/compiler/call.rb +45 -0
- data/lib/mirah/compiler/class.rb +81 -0
- data/lib/mirah/compiler/flow.rb +109 -0
- data/lib/mirah/compiler/literal.rb +130 -0
- data/lib/mirah/compiler/local.rb +59 -0
- data/lib/mirah/compiler/method.rb +44 -0
- data/lib/mirah/compiler/structure.rb +65 -0
- data/lib/mirah/compiler/type.rb +27 -0
- data/lib/mirah/env.rb +4 -6
- data/lib/mirah/generator.rb +61 -0
- data/lib/mirah/jvm/compiler.rb +8 -867
- data/lib/mirah/jvm/compiler/base.rb +270 -0
- data/lib/mirah/jvm/compiler/java_source.rb +779 -0
- data/lib/mirah/jvm/compiler/jvm_bytecode.rb +851 -0
- data/lib/mirah/jvm/method_lookup.rb +21 -2
- data/lib/mirah/jvm/source_generator/builder.rb +10 -13
- data/lib/mirah/jvm/source_generator/loops.rb +99 -93
- data/lib/mirah/jvm/source_generator/precompile.rb +3 -2
- data/lib/mirah/jvm/typer.rb +3 -3
- data/lib/mirah/jvm/types.rb +10 -426
- data/lib/mirah/jvm/types/array_type.rb +62 -0
- data/lib/mirah/jvm/types/basic_types.rb +1 -0
- data/lib/mirah/jvm/types/dynamic_type.rb +46 -0
- data/lib/mirah/jvm/types/factory.rb +23 -5
- data/lib/mirah/jvm/types/interface_definition.rb +20 -0
- data/lib/mirah/jvm/types/intrinsics.rb +15 -3
- data/lib/mirah/jvm/types/meta_type.rb +45 -0
- data/lib/mirah/jvm/types/methods.rb +12 -5
- data/lib/mirah/jvm/types/null_type.rb +27 -0
- data/lib/mirah/jvm/types/primitive_type.rb +38 -0
- data/lib/mirah/jvm/types/source_mirror.rb +266 -0
- data/lib/mirah/jvm/types/type.rb +173 -0
- data/lib/mirah/jvm/types/type_definition.rb +55 -0
- data/lib/mirah/jvm/types/unreachable_type.rb +27 -0
- data/lib/mirah/jvm/types/void_type.rb +19 -0
- data/lib/mirah/parser.rb +90 -0
- data/lib/mirah/plugin/gwt.rb +5 -5
- data/lib/mirah/plugin/java.rb +1 -1
- data/lib/mirah/transform.rb +4 -321
- data/lib/mirah/transform/ast_ext.rb +63 -0
- data/lib/mirah/transform/error.rb +13 -0
- data/lib/mirah/transform/helper.rb +761 -0
- data/lib/mirah/transform/transformer.rb +255 -0
- data/lib/mirah/typer.rb +2 -383
- data/{bin/duby → lib/mirah/typer/base.rb} +12 -10
- data/lib/mirah/typer/simple.rb +377 -0
- data/lib/mirah/util/argument_processor.rb +114 -0
- data/lib/mirah/util/class_loader.rb +37 -0
- data/lib/mirah/util/compilation_state.rb +51 -0
- data/lib/mirah/util/process_errors.rb +33 -0
- data/lib/mirah/version.rb +1 -1
- data/lib/mirah_task.rb +3 -2
- data/test/{test_ast.rb → core/test_ast.rb} +6 -0
- data/test/{test_compilation.rb → core/test_compilation.rb} +0 -0
- data/test/{test_env.rb → core/test_env.rb} +24 -25
- data/test/{test_macros.rb → core/test_macros.rb} +2 -4
- data/test/{test_typer.rb → core/test_typer.rb} +0 -3
- data/test/jvm/bytecode_test_helper.rb +181 -0
- data/test/{test_javac_compiler.rb → jvm/javac_test_helper.rb} +38 -22
- data/test/jvm/test_enumerable.rb +304 -0
- data/test/{test_java_typer.rb → jvm/test_java_typer.rb} +2 -4
- data/test/{test_jvm_compiler.rb → jvm/test_jvm_compiler.rb} +146 -443
- data/test/jvm/test_macros.rb +147 -0
- data/test/jvm/test_main_method.rb +15 -0
- data/test/{test_gwt.rb → plugins/test_gwt.rb} +0 -2
- metadata +103 -91
- data/bin/jrubyp +0 -52
- data/examples/wiki/src/org/mirah/wiki/MirahWiki.duby +0 -339
- data/examples/wiki/src/org/mirah/wiki/edit.eduby.html +0 -42
- data/examples/wiki/src/org/mirah/wiki/error.eduby.html +0 -2
- data/examples/wiki/src/org/mirah/wiki/layout.eduby.html +0 -69
- data/examples/wiki/src/org/mirah/wiki/parser.eduby.html +0 -7
- data/examples/wiki/src/org/mirah/wiki/view.eduby.html +0 -15
- data/examples/wiki/war/WEB-INF/classes/test/HeredocContext.class +0 -0
- data/examples/wiki/war/WEB-INF/classes/test/MirahParser.class +0 -0
- data/examples/wiki/war/WEB-INF/lib/appengine-api.jar +0 -0
- data/examples/wiki/war/WEB-INF/lib/dubydatastore.jar +0 -0
- data/examples/wiki/war/WEB-INF/lib/jmeta-runtime.jar +0 -0
- data/examples/wiki/war/WEB-INF/lib/pegdown-stubs.jar +0 -0
- data/examples/wiki/war/WEB-INF/pegdown.jar +0 -0
- data/examples/wiki/war/app.yaml +0 -21
- data/examples/wiki/war/public/favicon.ico +0 -0
- data/examples/wiki/war/public/images/appengine_duby.png +0 -0
- data/examples/wiki/war/public/images/back.gif +0 -0
- data/examples/wiki/war/public/images/dir.gif +0 -0
- data/examples/wiki/war/public/images/file.gif +0 -0
- data/examples/wiki/war/public/javascripts/prettify.js +0 -61
- data/examples/wiki/war/public/robots.txt +0 -0
- data/examples/wiki/war/public/stylesheets/main.css +0 -156
- data/examples/wiki/war/public/stylesheets/prettify.css +0 -1
- data/examples/wiki/war/public/stylesheets/sh_style.css +0 -66
- data/examples/wiki/war/public/stylesheets/source.css +0 -21
- data/examples/wiki/war/public/wmd/images/bg-fill.png +0 -0
- data/examples/wiki/war/public/wmd/images/bg.png +0 -0
- data/examples/wiki/war/public/wmd/images/blockquote.png +0 -0
- data/examples/wiki/war/public/wmd/images/bold.png +0 -0
- data/examples/wiki/war/public/wmd/images/code.png +0 -0
- data/examples/wiki/war/public/wmd/images/h1.png +0 -0
- data/examples/wiki/war/public/wmd/images/hr.png +0 -0
- data/examples/wiki/war/public/wmd/images/img.png +0 -0
- data/examples/wiki/war/public/wmd/images/italic.png +0 -0
- data/examples/wiki/war/public/wmd/images/link.png +0 -0
- data/examples/wiki/war/public/wmd/images/ol.png +0 -0
- data/examples/wiki/war/public/wmd/images/redo.png +0 -0
- data/examples/wiki/war/public/wmd/images/separator.png +0 -0
- data/examples/wiki/war/public/wmd/images/ul.png +0 -0
- data/examples/wiki/war/public/wmd/images/undo.png +0 -0
- data/examples/wiki/war/public/wmd/images/wmd-on.png +0 -0
- data/examples/wiki/war/public/wmd/images/wmd.png +0 -0
- data/examples/wiki/war/public/wmd/showdown.js +0 -421
- data/examples/wiki/war/public/wmd/wmd-base.js +0 -1799
- data/examples/wiki/war/public/wmd/wmd-plus.js +0 -311
- data/examples/wiki/war/public/wmd/wmd.js +0 -73
- data/examples/wiki/war/src/org/mirah/wiki/MirahWiki.duby +0 -339
- data/examples/wiki/war/src/org/mirah/wiki/edit.eduby.html +0 -42
- data/examples/wiki/war/src/org/mirah/wiki/error.eduby.html +0 -2
- data/examples/wiki/war/src/org/mirah/wiki/layout.eduby.html +0 -69
- data/examples/wiki/war/src/org/mirah/wiki/parser.eduby.html +0 -7
- data/examples/wiki/war/src/org/mirah/wiki/view.eduby.html +0 -15
- data/javalib/dynalink-0.1.jar +0 -0
- data/javalib/jsr292-mock.jar +0 -0
- data/lib/mirah/class_loader.rb +0 -35
- data/lib/mirah/compilation_state.rb +0 -28
- data/lib/mirah/impl.rb +0 -273
- data/lib/mirah/jvm/base.rb +0 -267
- data/lib/mirah/jvm/source_compiler.rb +0 -760
- data/lib/mirah/transform2.rb +0 -752
data/lib/mirah/jvm/base.rb
DELETED
|
@@ -1,267 +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 Compiler
|
|
18
|
-
class JVMCompilerBase
|
|
19
|
-
attr_accessor :filename, :method, :static, :class
|
|
20
|
-
|
|
21
|
-
class CompilationError < Mirah::NodeError
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def initialize
|
|
25
|
-
@jump_scope = []
|
|
26
|
-
@bindings = Hash.new {|h, type| h[type] = type.define(@file)}
|
|
27
|
-
@captured_locals = Hash.new {|h, binding| h[binding] = {}}
|
|
28
|
-
@self_scope = nil
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def error(message, node)
|
|
32
|
-
raise CompilationError.new(message, node)
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def compile(ast, expression = false)
|
|
36
|
-
begin
|
|
37
|
-
ast.compile(self, expression)
|
|
38
|
-
rescue => ex
|
|
39
|
-
raise Mirah::InternalCompilerError.wrap(ex, ast)
|
|
40
|
-
end
|
|
41
|
-
log "Compilation successful!"
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def log(message); JVM.log(message); end
|
|
45
|
-
|
|
46
|
-
def toplevel_class
|
|
47
|
-
@class = @type.define(@file)
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def generate
|
|
51
|
-
log "Generating #{output_type}..."
|
|
52
|
-
@file.generate do |filename, builder|
|
|
53
|
-
log " #{builder.class_name}"
|
|
54
|
-
if block_given?
|
|
55
|
-
yield filename, builder
|
|
56
|
-
else
|
|
57
|
-
File.open(filename, 'wb') {|f| f.write(builder.generate)}
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
log "...done!"
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
def define_main(script)
|
|
64
|
-
@static = true
|
|
65
|
-
@filename = File.basename(script.filename)
|
|
66
|
-
classname = JVM.classname_from_filename(@filename)
|
|
67
|
-
@type = AST.type(script, classname)
|
|
68
|
-
@file = file_builder(@filename)
|
|
69
|
-
body = script.body
|
|
70
|
-
body = body[0] if body.children.size == 1
|
|
71
|
-
if body.class != AST::ClassDefinition
|
|
72
|
-
@class = @type.define(@file)
|
|
73
|
-
with :method => @class.main do
|
|
74
|
-
log "Starting main method"
|
|
75
|
-
|
|
76
|
-
@method.start
|
|
77
|
-
@current_scope = script.static_scope
|
|
78
|
-
declare_locals(@current_scope)
|
|
79
|
-
begin_main
|
|
80
|
-
|
|
81
|
-
prepare_binding(script) do
|
|
82
|
-
body.compile(self, false)
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
finish_main
|
|
86
|
-
@method.stop
|
|
87
|
-
end
|
|
88
|
-
@class.stop
|
|
89
|
-
else
|
|
90
|
-
body.compile(self, false)
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
log "Main method complete!"
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
def begin_main; end
|
|
97
|
-
def finish_main; end
|
|
98
|
-
|
|
99
|
-
# arg_types must be an Array
|
|
100
|
-
def create_method_builder(name, node, static, exceptions, return_type, arg_types)
|
|
101
|
-
@class.build_method(name.to_s, node.visibility, static,
|
|
102
|
-
exceptions, return_type, *arg_types)
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
def base_define_method(node, args_are_types)
|
|
106
|
-
name, signature, args = node.name, node.signature, node.arguments.args
|
|
107
|
-
if name == "initialize" && node.static?
|
|
108
|
-
name = "<clinit>"
|
|
109
|
-
end
|
|
110
|
-
if args_are_types
|
|
111
|
-
arg_types = args.map { |arg| arg.inferred_type } if args
|
|
112
|
-
else
|
|
113
|
-
arg_types = args
|
|
114
|
-
end
|
|
115
|
-
arg_types ||= []
|
|
116
|
-
return_type = signature[:return]
|
|
117
|
-
exceptions = signature[:throws]
|
|
118
|
-
|
|
119
|
-
with :static => @static || node.static?, :current_scope => node.static_scope do
|
|
120
|
-
method = create_method_builder(name, node, @static, exceptions,
|
|
121
|
-
return_type, arg_types)
|
|
122
|
-
annotate(method, node.annotations)
|
|
123
|
-
yield method, arg_types
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
arg_types_for_opt = []
|
|
127
|
-
args_for_opt = []
|
|
128
|
-
if args
|
|
129
|
-
args.each do |arg|
|
|
130
|
-
if AST::OptionalArgument === arg
|
|
131
|
-
new_args = if args_are_types
|
|
132
|
-
arg_types_for_opt
|
|
133
|
-
else
|
|
134
|
-
args_for_opt
|
|
135
|
-
end
|
|
136
|
-
method = create_method_builder(name, node, @static, exceptions,
|
|
137
|
-
return_type, new_args)
|
|
138
|
-
with :method => method do
|
|
139
|
-
log "Starting new method #{name}(#{arg_types_for_opt})"
|
|
140
|
-
|
|
141
|
-
annotate(method, node.annotations)
|
|
142
|
-
@method.start
|
|
143
|
-
|
|
144
|
-
define_optarg_chain(name, arg,
|
|
145
|
-
return_type,
|
|
146
|
-
args_for_opt,
|
|
147
|
-
arg_types_for_opt)
|
|
148
|
-
|
|
149
|
-
@method.stop
|
|
150
|
-
end
|
|
151
|
-
end
|
|
152
|
-
arg_types_for_opt << arg.inferred_type
|
|
153
|
-
args_for_opt << arg
|
|
154
|
-
end
|
|
155
|
-
end
|
|
156
|
-
end
|
|
157
|
-
|
|
158
|
-
def constructor(node, args_are_types)
|
|
159
|
-
args = node.arguments.args || []
|
|
160
|
-
arg_types = if args_are_types
|
|
161
|
-
args.map { |arg| arg.inferred_type }
|
|
162
|
-
else
|
|
163
|
-
args
|
|
164
|
-
end
|
|
165
|
-
exceptions = node.signature[:throws]
|
|
166
|
-
method = @class.build_constructor(node.visibility, exceptions, *arg_types)
|
|
167
|
-
annotate(method, node.annotations)
|
|
168
|
-
with :current_scope => node.static_scope do
|
|
169
|
-
yield(method, args)
|
|
170
|
-
end
|
|
171
|
-
end
|
|
172
|
-
|
|
173
|
-
def define_class(class_def, expression)
|
|
174
|
-
with(:type => class_def.inferred_type,
|
|
175
|
-
:class => class_def.inferred_type.define(@file),
|
|
176
|
-
:static => false) do
|
|
177
|
-
annotate(@class, class_def.annotations)
|
|
178
|
-
class_def.body.compile(self, false) if class_def.body
|
|
179
|
-
@class.stop
|
|
180
|
-
end
|
|
181
|
-
end
|
|
182
|
-
|
|
183
|
-
def declare_argument(name, type)
|
|
184
|
-
# declare local vars for arguments here
|
|
185
|
-
end
|
|
186
|
-
|
|
187
|
-
def body(body, expression)
|
|
188
|
-
saved_self = @self_scope
|
|
189
|
-
if body.kind_of?(Mirah::AST::ScopedBody)
|
|
190
|
-
scope = body.static_scope
|
|
191
|
-
declare_locals(scope)
|
|
192
|
-
if scope != @self_scope
|
|
193
|
-
if scope.self_node && scope.self_node != :self
|
|
194
|
-
# FIXME This is a horrible hack!
|
|
195
|
-
# Instead we should eliminate unused self's.
|
|
196
|
-
unless scope.self_type.name == 'mirah.impl.Builtin'
|
|
197
|
-
local_assign(
|
|
198
|
-
scope, 'self', scope.self_type, false, scope.self_node)
|
|
199
|
-
end
|
|
200
|
-
end
|
|
201
|
-
@self_scope = scope
|
|
202
|
-
end
|
|
203
|
-
end
|
|
204
|
-
# all except the last element in a body of code is treated as a statement
|
|
205
|
-
i, last = 0, body.children.size - 1
|
|
206
|
-
while i < last
|
|
207
|
-
body.children[i].compile(self, false)
|
|
208
|
-
i += 1
|
|
209
|
-
end
|
|
210
|
-
yield body.children[last] if last >= 0
|
|
211
|
-
@self_scope = saved_self
|
|
212
|
-
end
|
|
213
|
-
|
|
214
|
-
def scoped_body(scope, expression)
|
|
215
|
-
body(scope, expression)
|
|
216
|
-
end
|
|
217
|
-
|
|
218
|
-
def scoped_local_name(name, scope=nil)
|
|
219
|
-
if scope.nil? || scope == @current_scope
|
|
220
|
-
name
|
|
221
|
-
else
|
|
222
|
-
"#{name}$#{scope.object_id}"
|
|
223
|
-
end
|
|
224
|
-
end
|
|
225
|
-
|
|
226
|
-
def import(short, long)
|
|
227
|
-
end
|
|
228
|
-
|
|
229
|
-
def fixnum(type, value)
|
|
230
|
-
type.literal(method, value)
|
|
231
|
-
end
|
|
232
|
-
alias float fixnum
|
|
233
|
-
|
|
234
|
-
def compile_self
|
|
235
|
-
if @self_scope && @self_scope.self_node && @self_scope.self_node != :self
|
|
236
|
-
local(@self_scope, 'self', @self_scope.self_type)
|
|
237
|
-
else
|
|
238
|
-
real_self
|
|
239
|
-
end
|
|
240
|
-
end
|
|
241
|
-
|
|
242
|
-
def get_binding(type)
|
|
243
|
-
@bindings[type]
|
|
244
|
-
end
|
|
245
|
-
|
|
246
|
-
def declared_captures(binding=nil)
|
|
247
|
-
@captured_locals[binding || @binding]
|
|
248
|
-
end
|
|
249
|
-
|
|
250
|
-
def with(vars)
|
|
251
|
-
orig_values = {}
|
|
252
|
-
begin
|
|
253
|
-
vars.each do |name, new_value|
|
|
254
|
-
name = "@#{name}"
|
|
255
|
-
orig_values[name] = instance_variable_get name
|
|
256
|
-
instance_variable_set name, new_value
|
|
257
|
-
end
|
|
258
|
-
yield
|
|
259
|
-
ensure
|
|
260
|
-
orig_values.each do |name, value|
|
|
261
|
-
instance_variable_set name, value
|
|
262
|
-
end
|
|
263
|
-
end
|
|
264
|
-
end
|
|
265
|
-
end
|
|
266
|
-
end
|
|
267
|
-
end
|
|
@@ -1,760 +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/ast'
|
|
18
|
-
require 'mirah/jvm/types'
|
|
19
|
-
require 'mirah/jvm/compiler'
|
|
20
|
-
require 'mirah/jvm/source_generator/builder'
|
|
21
|
-
require 'mirah/jvm/source_generator/precompile'
|
|
22
|
-
require 'mirah/jvm/source_generator/loops'
|
|
23
|
-
|
|
24
|
-
class String
|
|
25
|
-
def compile(compiler, expression)
|
|
26
|
-
compiler.method.print self if expression
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
module Mirah
|
|
31
|
-
module Compiler
|
|
32
|
-
class JavaSource < JVMCompilerBase
|
|
33
|
-
JVMTypes = Mirah::JVM::Types
|
|
34
|
-
attr_accessor :lvalue
|
|
35
|
-
|
|
36
|
-
Operators = [
|
|
37
|
-
'+', '-', '+@', '-@', '/', '%', '*', '<',
|
|
38
|
-
'<=', '==', '!=', '>=', '>',
|
|
39
|
-
'<<', '>>', '>>>', '|', '&', '^', '~'
|
|
40
|
-
]
|
|
41
|
-
ArrayOps = [
|
|
42
|
-
'[]', '[]=', 'length'
|
|
43
|
-
]
|
|
44
|
-
|
|
45
|
-
ImplicitReturn = Struct.new(:value)
|
|
46
|
-
|
|
47
|
-
def initialize
|
|
48
|
-
super
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def file_builder(filename)
|
|
52
|
-
Mirah::JavaSource::Builder.new(filename, self)
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def output_type
|
|
56
|
-
"source files"
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def define_method(node)
|
|
60
|
-
base_define_method(node, false) do |method, _|
|
|
61
|
-
with :method => method do
|
|
62
|
-
log "Starting new method #{node.name}"
|
|
63
|
-
@method.start
|
|
64
|
-
|
|
65
|
-
prepare_binding(node) do
|
|
66
|
-
declare_locals(node.static_scope)
|
|
67
|
-
unless @method.type.nil? || @method.type.void?
|
|
68
|
-
self.return(ImplicitReturn.new(node.body))
|
|
69
|
-
else
|
|
70
|
-
node.body.compile(self, false) if node.body
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
log "Method #{node.name} complete!"
|
|
75
|
-
@method.stop
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
def annotate(node, annotations)
|
|
81
|
-
node.annotate(annotations)
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
def define_optarg_chain(name, arg, return_type,
|
|
85
|
-
args_for_opt, arg_types_for_opt)
|
|
86
|
-
# declare all args so they get their values
|
|
87
|
-
@method.print "return " unless @method.type.nil? || @method.type.void?
|
|
88
|
-
@method.print "this." unless @static
|
|
89
|
-
@method.print "#{name}("
|
|
90
|
-
@method.print args_for_opt.map(&:name).join(', ')
|
|
91
|
-
@method.print ', 'if args_for_opt.size > 0
|
|
92
|
-
arg.value.compile(self, true)
|
|
93
|
-
|
|
94
|
-
# invoke the next one in the chain
|
|
95
|
-
@method.print ");\n"
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
def constructor(node)
|
|
99
|
-
super(node, false) do |method, _|
|
|
100
|
-
with :method => method do
|
|
101
|
-
@method.start
|
|
102
|
-
if node.delegate_args
|
|
103
|
-
delegate = if node.calls_super
|
|
104
|
-
"super"
|
|
105
|
-
else
|
|
106
|
-
"this"
|
|
107
|
-
end
|
|
108
|
-
method.print "#{delegate}("
|
|
109
|
-
node.delegate_args.each_with_index do |arg, index|
|
|
110
|
-
method.print ', ' unless index == 0
|
|
111
|
-
raise "Invalid constructor argument #{arg}" unless arg.expr?(self)
|
|
112
|
-
arg.compile(self, true)
|
|
113
|
-
end
|
|
114
|
-
method.puts ");"
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
prepare_binding(node) do
|
|
118
|
-
declare_locals(node.static_scope)
|
|
119
|
-
node.body.compile(self, false) if node.body
|
|
120
|
-
end
|
|
121
|
-
method.stop
|
|
122
|
-
end
|
|
123
|
-
end
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
def prepare_binding(scope)
|
|
127
|
-
if scope.has_binding?
|
|
128
|
-
type = scope.binding_type
|
|
129
|
-
@binding = @bindings[type]
|
|
130
|
-
@method.puts "#{type.to_source} $binding = new #{type.to_source}();"
|
|
131
|
-
if scope.respond_to? :arguments
|
|
132
|
-
scope.arguments.args.each do |param|
|
|
133
|
-
if scope.static_scope.captured?(param.name)
|
|
134
|
-
captured_local_declare(scope, param.name, param.inferred_type)
|
|
135
|
-
@method.puts "$binding.#{param.name} = #{param.name};"
|
|
136
|
-
end
|
|
137
|
-
end
|
|
138
|
-
end
|
|
139
|
-
end
|
|
140
|
-
begin
|
|
141
|
-
yield
|
|
142
|
-
ensure
|
|
143
|
-
if scope.has_binding?
|
|
144
|
-
@binding.stop
|
|
145
|
-
@binding = nil
|
|
146
|
-
end
|
|
147
|
-
end
|
|
148
|
-
end
|
|
149
|
-
|
|
150
|
-
def define_closure(class_def, expression)
|
|
151
|
-
compiler = ClosureCompiler.new(@file, @type, self)
|
|
152
|
-
compiler.define_class(class_def, expression)
|
|
153
|
-
end
|
|
154
|
-
|
|
155
|
-
def return(node)
|
|
156
|
-
if @method.type.nil? || @method.type.void?
|
|
157
|
-
@method.puts 'return;'
|
|
158
|
-
return
|
|
159
|
-
end
|
|
160
|
-
if node.value.expr?(self)
|
|
161
|
-
@method.print 'return '
|
|
162
|
-
node.value.compile(self, true)
|
|
163
|
-
@method.puts ';'
|
|
164
|
-
else
|
|
165
|
-
store_value('return ', node.value)
|
|
166
|
-
end
|
|
167
|
-
end
|
|
168
|
-
|
|
169
|
-
def _raise(node)
|
|
170
|
-
if node.expr?(self)
|
|
171
|
-
@method.print 'throw '
|
|
172
|
-
node.compile(self, true)
|
|
173
|
-
@method.puts ';'
|
|
174
|
-
else
|
|
175
|
-
store_value('throw ', node)
|
|
176
|
-
end
|
|
177
|
-
end
|
|
178
|
-
|
|
179
|
-
def rescue(node, expression)
|
|
180
|
-
@method.block 'try' do
|
|
181
|
-
maybe_store(node.body, expression)
|
|
182
|
-
end
|
|
183
|
-
node.clauses.each do |clause|
|
|
184
|
-
clause.types.each do |type|
|
|
185
|
-
name = scoped_local_name(clause.name || 'tmp$ex', clause.static_scope)
|
|
186
|
-
@method.declare_local(type, name, false)
|
|
187
|
-
@method.block "catch (#{type.to_source} #{name})" do
|
|
188
|
-
declare_locals(clause.static_scope)
|
|
189
|
-
maybe_store(clause.body, expression)
|
|
190
|
-
end
|
|
191
|
-
end
|
|
192
|
-
end
|
|
193
|
-
end
|
|
194
|
-
|
|
195
|
-
def ensure(node, expression)
|
|
196
|
-
@method.block 'try' do
|
|
197
|
-
maybe_store(node.body, expression)
|
|
198
|
-
end
|
|
199
|
-
@method.block 'finally' do
|
|
200
|
-
node.clause.compile(self, false)
|
|
201
|
-
end
|
|
202
|
-
end
|
|
203
|
-
|
|
204
|
-
def line(num)
|
|
205
|
-
end
|
|
206
|
-
|
|
207
|
-
def declare_local(name, type)
|
|
208
|
-
@method.declare_local(type, name)
|
|
209
|
-
end
|
|
210
|
-
|
|
211
|
-
def declare_field(name, type, annotations, static_field)
|
|
212
|
-
@class.declare_field(name, type, @static || static_field, 'private', annotations)
|
|
213
|
-
end
|
|
214
|
-
|
|
215
|
-
def local(scope, name, type)
|
|
216
|
-
name = scoped_local_name(name, scope)
|
|
217
|
-
@method.print name
|
|
218
|
-
end
|
|
219
|
-
|
|
220
|
-
def field(name, type, annotations, static_field)
|
|
221
|
-
name = name[1..-1] if name =~ /^@/
|
|
222
|
-
declare_field(name, type, annotations, static_field)
|
|
223
|
-
@method.print "#{this}.#{name}"
|
|
224
|
-
end
|
|
225
|
-
|
|
226
|
-
def this(method=nil)
|
|
227
|
-
if method && method.static?
|
|
228
|
-
method.declaring_class.name
|
|
229
|
-
elsif @self_scope && @self_scope.self_node && @self_scope.self_node != :self
|
|
230
|
-
scoped_local_name('self', @self_scope)
|
|
231
|
-
else
|
|
232
|
-
@static ? @class.class_name : 'this'
|
|
233
|
-
end
|
|
234
|
-
end
|
|
235
|
-
|
|
236
|
-
def declare_locals(scope)
|
|
237
|
-
scope.locals.each do |name|
|
|
238
|
-
full_name = scoped_local_name(name, scope)
|
|
239
|
-
unless scope.captured?(name) || method.local?(full_name)
|
|
240
|
-
declare_local(full_name, scope.local_type(name))
|
|
241
|
-
end
|
|
242
|
-
end
|
|
243
|
-
end
|
|
244
|
-
|
|
245
|
-
def local_assign(scope, name, type, expression, value)
|
|
246
|
-
simple = value.expr?(self)
|
|
247
|
-
value = value.precompile(self)
|
|
248
|
-
name = scoped_local_name(name, scope)
|
|
249
|
-
if method.local?(name)
|
|
250
|
-
if expression
|
|
251
|
-
if simple
|
|
252
|
-
@method.print '('
|
|
253
|
-
else
|
|
254
|
-
@method.print @lvalue
|
|
255
|
-
end
|
|
256
|
-
end
|
|
257
|
-
@method.print "#{name} = "
|
|
258
|
-
value.compile(self, true)
|
|
259
|
-
if simple && expression
|
|
260
|
-
@method.print ')'
|
|
261
|
-
else
|
|
262
|
-
@method.puts ';'
|
|
263
|
-
end
|
|
264
|
-
else
|
|
265
|
-
@method.declare_local(type, name) do
|
|
266
|
-
value.compile(self, true)
|
|
267
|
-
end
|
|
268
|
-
if expression
|
|
269
|
-
@method.puts "#{@lvalue}#{name};"
|
|
270
|
-
end
|
|
271
|
-
end
|
|
272
|
-
end
|
|
273
|
-
|
|
274
|
-
def field_declare(name, type, annotations)
|
|
275
|
-
name = name[1..-1] if name =~ /^@/
|
|
276
|
-
declare_field(name, type, annotations)
|
|
277
|
-
end
|
|
278
|
-
|
|
279
|
-
def local_declare(scope, name, type)
|
|
280
|
-
name = scoped_local_name(name, scope)
|
|
281
|
-
declare_local(name, type)
|
|
282
|
-
end
|
|
283
|
-
|
|
284
|
-
def field_assign(name, type, expression, value, annotations, static_field)
|
|
285
|
-
name = name[1..-1] if name =~ /^@/
|
|
286
|
-
declare_field(name, type, annotations, static_field)
|
|
287
|
-
lvalue = "#{@lvalue if expression}#{this}.#{name} = "
|
|
288
|
-
store_value(lvalue, value)
|
|
289
|
-
end
|
|
290
|
-
|
|
291
|
-
def captured_local_declare(scope, name, type)
|
|
292
|
-
unless declared_captures[name]
|
|
293
|
-
declared_captures[name] = type
|
|
294
|
-
@binding.declare_field(name, type, false, '')
|
|
295
|
-
end
|
|
296
|
-
end
|
|
297
|
-
|
|
298
|
-
def captured_local(scope, name, type)
|
|
299
|
-
captured_local_declare(scope, name, type)
|
|
300
|
-
@method.print "$binding.#{name}"
|
|
301
|
-
end
|
|
302
|
-
|
|
303
|
-
def captured_local_assign(node, expression)
|
|
304
|
-
scope, name, type = node.containing_scope, node.name, node.inferred_type
|
|
305
|
-
captured_local_declare(scope, name, type)
|
|
306
|
-
lvalue = "#{@lvalue if expression}$binding.#{name} = "
|
|
307
|
-
store_value(lvalue, node.value)
|
|
308
|
-
end
|
|
309
|
-
|
|
310
|
-
def store_value(lvalue, value)
|
|
311
|
-
if value.is_a? String
|
|
312
|
-
@method.puts "#{lvalue}#{value};"
|
|
313
|
-
elsif value.expr?(self)
|
|
314
|
-
@method.print lvalue
|
|
315
|
-
value.compile(self, true)
|
|
316
|
-
@method.puts ';'
|
|
317
|
-
else
|
|
318
|
-
with :lvalue => lvalue do
|
|
319
|
-
value.compile(self, true)
|
|
320
|
-
end
|
|
321
|
-
end
|
|
322
|
-
end
|
|
323
|
-
|
|
324
|
-
def assign(name, value)
|
|
325
|
-
store_value("#{name} = ", value)
|
|
326
|
-
name
|
|
327
|
-
end
|
|
328
|
-
|
|
329
|
-
def maybe_store(value, expression)
|
|
330
|
-
if expression
|
|
331
|
-
store_value(@lvalue, value)
|
|
332
|
-
else
|
|
333
|
-
value.compile(self, false)
|
|
334
|
-
end
|
|
335
|
-
end
|
|
336
|
-
|
|
337
|
-
def body(body, expression)
|
|
338
|
-
super(body, expression) do |last|
|
|
339
|
-
maybe_store(last, expression)
|
|
340
|
-
end
|
|
341
|
-
end
|
|
342
|
-
|
|
343
|
-
def scoped_body(scope, expression)
|
|
344
|
-
@method.block do
|
|
345
|
-
super
|
|
346
|
-
end
|
|
347
|
-
end
|
|
348
|
-
|
|
349
|
-
def branch_expression(node)
|
|
350
|
-
node.condition.compile(self, true)
|
|
351
|
-
@method.print ' ? ('
|
|
352
|
-
if node.body
|
|
353
|
-
node.body.compile(self, true)
|
|
354
|
-
else
|
|
355
|
-
@method.print @method.init_value(node.inferred_type)
|
|
356
|
-
end
|
|
357
|
-
@method.print ') : ('
|
|
358
|
-
if node.else
|
|
359
|
-
node.else.compile(self, true)
|
|
360
|
-
else
|
|
361
|
-
@method.print @method.init_value(node.inferred_type)
|
|
362
|
-
end
|
|
363
|
-
@method.print ')'
|
|
364
|
-
end
|
|
365
|
-
|
|
366
|
-
def branch(node, expression)
|
|
367
|
-
if expression && node.expr?(self)
|
|
368
|
-
return branch_expression(node)
|
|
369
|
-
end
|
|
370
|
-
predicate = node.condition.predicate.precompile(self)
|
|
371
|
-
@method.print 'if ('
|
|
372
|
-
predicate.compile(self, true)
|
|
373
|
-
@method.block ")" do
|
|
374
|
-
if node.body
|
|
375
|
-
maybe_store(node.body, expression)
|
|
376
|
-
elsif expression
|
|
377
|
-
store_value(@lvalue, @method.init_value(node.inferred_type))
|
|
378
|
-
end
|
|
379
|
-
end
|
|
380
|
-
if node.else || expression
|
|
381
|
-
@method.block 'else' do
|
|
382
|
-
if node.else
|
|
383
|
-
maybe_store(node.else, expression)
|
|
384
|
-
else
|
|
385
|
-
store_value(@lvalue, @method.init_value(node.inferred_type))
|
|
386
|
-
end
|
|
387
|
-
end
|
|
388
|
-
end
|
|
389
|
-
end
|
|
390
|
-
|
|
391
|
-
def loop(loop, expression)
|
|
392
|
-
if loop.redo? || loop.post || !loop.condition.predicate.expr?(self)
|
|
393
|
-
loop = ComplexWhileLoop.new(loop, self)
|
|
394
|
-
else
|
|
395
|
-
loop = SimpleWhileLoop.new(loop, self)
|
|
396
|
-
end
|
|
397
|
-
with(:loop => loop) do
|
|
398
|
-
loop.compile(expression)
|
|
399
|
-
end
|
|
400
|
-
end
|
|
401
|
-
|
|
402
|
-
def expr?(target, params)
|
|
403
|
-
!([target] + params).any? {|x| x.kind_of? Mirah::AST::TempValue}
|
|
404
|
-
end
|
|
405
|
-
|
|
406
|
-
def operator(target, op, params, expression)
|
|
407
|
-
simple = expr?(target, params)
|
|
408
|
-
if expression && !simple
|
|
409
|
-
@method.print @lvalue
|
|
410
|
-
end
|
|
411
|
-
if params.size == 0
|
|
412
|
-
# unary operator
|
|
413
|
-
op = op[0,1]
|
|
414
|
-
@method.print op
|
|
415
|
-
target.compile(self, true)
|
|
416
|
-
else
|
|
417
|
-
@method.print '('
|
|
418
|
-
other = params[0]
|
|
419
|
-
target.compile(self, true)
|
|
420
|
-
@method.print " #{op} "
|
|
421
|
-
other.compile(self, true)
|
|
422
|
-
@method.print ')'
|
|
423
|
-
end
|
|
424
|
-
unless expression && simple
|
|
425
|
-
@method.puts ';'
|
|
426
|
-
end
|
|
427
|
-
end
|
|
428
|
-
|
|
429
|
-
def precompile_nodes(nodes)
|
|
430
|
-
if nodes.all? {|n| n.expr?(self)}
|
|
431
|
-
nodes
|
|
432
|
-
else
|
|
433
|
-
nodes.map do |node|
|
|
434
|
-
tempval = node.precompile(self)
|
|
435
|
-
if node == tempval && !node.kind_of?(Mirah::AST::Literal)
|
|
436
|
-
tempval = node.temp(self)
|
|
437
|
-
end
|
|
438
|
-
tempval
|
|
439
|
-
end
|
|
440
|
-
end
|
|
441
|
-
end
|
|
442
|
-
|
|
443
|
-
def compile_args(call)
|
|
444
|
-
precompile_nodes(call.parameters)
|
|
445
|
-
end
|
|
446
|
-
|
|
447
|
-
def self_type
|
|
448
|
-
type = AST.type(nil, @class.name.tr('/', '.'))
|
|
449
|
-
type = type.meta if @static
|
|
450
|
-
type
|
|
451
|
-
end
|
|
452
|
-
|
|
453
|
-
def super_call(call, expression)
|
|
454
|
-
super_method_call(this, call, compile_args(call), expression)
|
|
455
|
-
end
|
|
456
|
-
|
|
457
|
-
def cast(call, expression)
|
|
458
|
-
args = compile_args(call)
|
|
459
|
-
simple = call.expr?(self)
|
|
460
|
-
@method.print @lvalue if expression && !simple
|
|
461
|
-
@method.print "((#{call.inferred_type.to_source})("
|
|
462
|
-
args.each{|arg| arg.compile(self, true)}
|
|
463
|
-
@method.print "))"
|
|
464
|
-
@method.puts ';' unless simple && expression
|
|
465
|
-
end
|
|
466
|
-
|
|
467
|
-
def self_call(call, expression)
|
|
468
|
-
if call.cast?
|
|
469
|
-
cast(call, expression)
|
|
470
|
-
else
|
|
471
|
-
type = call.scope.static_scope.self_type
|
|
472
|
-
type = type.meta if (@static && type == @type)
|
|
473
|
-
params = call.parameters.map do |param|
|
|
474
|
-
param.inferred_type
|
|
475
|
-
end
|
|
476
|
-
method = type.get_method(call.name, params)
|
|
477
|
-
method_call(this(method), call, compile_args(call), expression)
|
|
478
|
-
end
|
|
479
|
-
end
|
|
480
|
-
|
|
481
|
-
def call(call, expression)
|
|
482
|
-
return cast(call, expression) if call.cast?
|
|
483
|
-
if Mirah::AST::Constant === call.target || Mirah::AST::Colon2 === call.target
|
|
484
|
-
target = call.target.inferred_type.to_source
|
|
485
|
-
else
|
|
486
|
-
target = call.precompile_target(self)
|
|
487
|
-
end
|
|
488
|
-
params = compile_args(call)
|
|
489
|
-
|
|
490
|
-
if Operators.include? call.name
|
|
491
|
-
operator(target, call.name, params, expression)
|
|
492
|
-
elsif call.target.inferred_type.array? && ArrayOps.include?(call.name)
|
|
493
|
-
array_op(target, call.name, params, expression)
|
|
494
|
-
elsif call.name == 'nil?'
|
|
495
|
-
operator(target, '==', ['null'], expression)
|
|
496
|
-
else
|
|
497
|
-
method_call(target, call, params, expression)
|
|
498
|
-
end
|
|
499
|
-
end
|
|
500
|
-
|
|
501
|
-
def array_op(target, name, args, expression)
|
|
502
|
-
simple = expr?(target, args)
|
|
503
|
-
index, value = args
|
|
504
|
-
if expression && !simple
|
|
505
|
-
@method.print @lvalue
|
|
506
|
-
end
|
|
507
|
-
target.compile(self, true)
|
|
508
|
-
if name == 'length'
|
|
509
|
-
@method.print '.length'
|
|
510
|
-
else
|
|
511
|
-
@method.print '['
|
|
512
|
-
index.compile(self, true)
|
|
513
|
-
@method.print ']'
|
|
514
|
-
if name == '[]='
|
|
515
|
-
@method.print " = "
|
|
516
|
-
value.compile(self, true)
|
|
517
|
-
end
|
|
518
|
-
end
|
|
519
|
-
unless simple && expression
|
|
520
|
-
@method.puts ';'
|
|
521
|
-
end
|
|
522
|
-
end
|
|
523
|
-
|
|
524
|
-
def break(node)
|
|
525
|
-
error("break outside of loop", node) unless @loop
|
|
526
|
-
@loop.break
|
|
527
|
-
end
|
|
528
|
-
|
|
529
|
-
def next(node)
|
|
530
|
-
error("next outside of loop", node) unless @loop
|
|
531
|
-
@loop.next
|
|
532
|
-
end
|
|
533
|
-
|
|
534
|
-
def redo(node)
|
|
535
|
-
error("redo outside of loop", node) unless @loop
|
|
536
|
-
@loop.redo
|
|
537
|
-
end
|
|
538
|
-
|
|
539
|
-
# TODO: merge cleanly with method_call logic
|
|
540
|
-
def super_method_call(target, call, params, expression)
|
|
541
|
-
simple = call.expr?(self)
|
|
542
|
-
method = call.method(self)
|
|
543
|
-
unless simple || method.return_type.void?
|
|
544
|
-
@method.print @lvalue if expression
|
|
545
|
-
end
|
|
546
|
-
if method.constructor?
|
|
547
|
-
@method.print "super("
|
|
548
|
-
else
|
|
549
|
-
@method.print "super.#{method.name}("
|
|
550
|
-
end
|
|
551
|
-
params.each_with_index do |param, index|
|
|
552
|
-
@method.print ', ' unless index == 0
|
|
553
|
-
param.compile(self, true)
|
|
554
|
-
end
|
|
555
|
-
if simple && expression
|
|
556
|
-
@method.print ')'
|
|
557
|
-
else
|
|
558
|
-
@method.puts ');'
|
|
559
|
-
end
|
|
560
|
-
if method.return_type.void? && expression
|
|
561
|
-
@method.print @lvalue
|
|
562
|
-
if method.static?
|
|
563
|
-
@method.puts 'null;'
|
|
564
|
-
else
|
|
565
|
-
target.compile(self, true)
|
|
566
|
-
@method.puts ';'
|
|
567
|
-
end
|
|
568
|
-
end
|
|
569
|
-
|
|
570
|
-
end
|
|
571
|
-
|
|
572
|
-
def method_call(target, call, params, expression)
|
|
573
|
-
simple = call.expr?(self)
|
|
574
|
-
method = call.method(self)
|
|
575
|
-
unless simple || method.return_type.void?
|
|
576
|
-
@method.print @lvalue if expression
|
|
577
|
-
end
|
|
578
|
-
|
|
579
|
-
# preamble
|
|
580
|
-
if method.constructor?
|
|
581
|
-
@method.print "new "
|
|
582
|
-
target.compile(self, true)
|
|
583
|
-
@method.print '('
|
|
584
|
-
elsif method.field?
|
|
585
|
-
target.compile(self, true)
|
|
586
|
-
@method.print ".#{method.name}"
|
|
587
|
-
if method.argument_types.size == 1
|
|
588
|
-
@method.print " = ("
|
|
589
|
-
end
|
|
590
|
-
elsif Mirah::JVM::Types::Intrinsic === method
|
|
591
|
-
method.call(self, call, expression)
|
|
592
|
-
return
|
|
593
|
-
else
|
|
594
|
-
target.compile(self, true)
|
|
595
|
-
@method.print ".#{method.name}("
|
|
596
|
-
end
|
|
597
|
-
|
|
598
|
-
# args
|
|
599
|
-
params.each_with_index do |param, index|
|
|
600
|
-
@method.print ', ' unless index == 0
|
|
601
|
-
param.compile(self, true)
|
|
602
|
-
end
|
|
603
|
-
|
|
604
|
-
# postamble
|
|
605
|
-
if !method.field? || (method.field? && method.argument_types.size == 1)
|
|
606
|
-
if simple && expression
|
|
607
|
-
@method.print ')'
|
|
608
|
-
else
|
|
609
|
-
@method.puts ');'
|
|
610
|
-
end
|
|
611
|
-
end
|
|
612
|
-
|
|
613
|
-
# cleanup
|
|
614
|
-
if method.return_type.void? && expression
|
|
615
|
-
@method.print @lvalue
|
|
616
|
-
if method.static?
|
|
617
|
-
@method.puts 'null;'
|
|
618
|
-
else
|
|
619
|
-
target.compile(self, true)
|
|
620
|
-
@method.puts ';'
|
|
621
|
-
end
|
|
622
|
-
end
|
|
623
|
-
end
|
|
624
|
-
|
|
625
|
-
def temp(expression, value=nil)
|
|
626
|
-
value ||= expression
|
|
627
|
-
type = value.inferred_type
|
|
628
|
-
if value.expr?(self)
|
|
629
|
-
@method.tmp(type) do
|
|
630
|
-
value.compile(self, true)
|
|
631
|
-
end
|
|
632
|
-
else
|
|
633
|
-
assign(@method.tmp(type), value)
|
|
634
|
-
end
|
|
635
|
-
end
|
|
636
|
-
|
|
637
|
-
def empty_array(type, size)
|
|
638
|
-
sizevar = size.precompile(self)
|
|
639
|
-
@method.print "#{@lvalue unless size.expr?(self)}new #{type.name}["
|
|
640
|
-
sizevar.compile(self, true)
|
|
641
|
-
@method.print ']'
|
|
642
|
-
end
|
|
643
|
-
|
|
644
|
-
def string(value)
|
|
645
|
-
@method.print value.inspect
|
|
646
|
-
end
|
|
647
|
-
|
|
648
|
-
def boolean(value)
|
|
649
|
-
@method.print value ? 'true' : 'false'
|
|
650
|
-
end
|
|
651
|
-
|
|
652
|
-
def regexp(value, flags = 0)
|
|
653
|
-
@method.print "java.util.regex.Pattern.compile("
|
|
654
|
-
@method.print value.inspect
|
|
655
|
-
@method.print ")"
|
|
656
|
-
end
|
|
657
|
-
|
|
658
|
-
def array(node, expression)
|
|
659
|
-
if expression
|
|
660
|
-
# create unmodifiable list from array (simplest way to do this in Java source)
|
|
661
|
-
@method.print "java.util.Collections.unmodifiableList(java.util.Arrays.asList("
|
|
662
|
-
|
|
663
|
-
# elements, as expressions
|
|
664
|
-
comma = false
|
|
665
|
-
node.children.each do |n|
|
|
666
|
-
@method.print ", " if comma
|
|
667
|
-
n.compile(self, true)
|
|
668
|
-
comma = true
|
|
669
|
-
end
|
|
670
|
-
|
|
671
|
-
@method.print("))")
|
|
672
|
-
else
|
|
673
|
-
# elements, as non-expressions
|
|
674
|
-
# TODO: ensure they're all reference types!
|
|
675
|
-
node.children.each do |n|
|
|
676
|
-
n.compile(self, false)
|
|
677
|
-
end
|
|
678
|
-
end
|
|
679
|
-
end
|
|
680
|
-
|
|
681
|
-
def build_string(orig_nodes, expression)
|
|
682
|
-
if expression
|
|
683
|
-
nodes = precompile_nodes(orig_nodes)
|
|
684
|
-
simple = nodes.equal?(orig_nodes)
|
|
685
|
-
if !simple
|
|
686
|
-
@method.print(lvalue)
|
|
687
|
-
end
|
|
688
|
-
first = true
|
|
689
|
-
unless nodes[0].kind_of?(Mirah::AST::String)
|
|
690
|
-
@method.print '""'
|
|
691
|
-
first = false
|
|
692
|
-
end
|
|
693
|
-
nodes.each do |node|
|
|
694
|
-
@method.print ' + ' unless first
|
|
695
|
-
first = false
|
|
696
|
-
node.compile(self, true)
|
|
697
|
-
end
|
|
698
|
-
@method.puts ';' unless simple
|
|
699
|
-
else
|
|
700
|
-
orig_nodes.each {|n| n.compile(self, false)}
|
|
701
|
-
end
|
|
702
|
-
end
|
|
703
|
-
|
|
704
|
-
def to_string(body, expression)
|
|
705
|
-
body.compile(self, expression)
|
|
706
|
-
end
|
|
707
|
-
|
|
708
|
-
def null
|
|
709
|
-
@method.print 'null'
|
|
710
|
-
end
|
|
711
|
-
|
|
712
|
-
def binding_reference
|
|
713
|
-
@method.print '$binding'
|
|
714
|
-
end
|
|
715
|
-
|
|
716
|
-
def real_self
|
|
717
|
-
@method.print 'this'
|
|
718
|
-
end
|
|
719
|
-
|
|
720
|
-
def print(node)
|
|
721
|
-
value = node.parameters[0]
|
|
722
|
-
value = value && value.precompile(self)
|
|
723
|
-
if node.println
|
|
724
|
-
@method.print "System.out.println("
|
|
725
|
-
else
|
|
726
|
-
@method.print "System.out.print("
|
|
727
|
-
end
|
|
728
|
-
value.compile(self, true) if value
|
|
729
|
-
@method.puts ');'
|
|
730
|
-
end
|
|
731
|
-
|
|
732
|
-
class ClosureCompiler < JavaSource
|
|
733
|
-
def initialize(file, type, parent)
|
|
734
|
-
@file = file
|
|
735
|
-
@type = type
|
|
736
|
-
@parent = parent
|
|
737
|
-
end
|
|
738
|
-
|
|
739
|
-
def prepare_binding(scope)
|
|
740
|
-
if scope.has_binding?
|
|
741
|
-
type = scope.binding_type
|
|
742
|
-
@binding = @parent.get_binding(type)
|
|
743
|
-
@method.puts("#{type.to_source} $binding = this.binding;")
|
|
744
|
-
end
|
|
745
|
-
begin
|
|
746
|
-
yield
|
|
747
|
-
ensure
|
|
748
|
-
if scope.has_binding?
|
|
749
|
-
@binding = nil
|
|
750
|
-
end
|
|
751
|
-
end
|
|
752
|
-
end
|
|
753
|
-
|
|
754
|
-
def declared_captures
|
|
755
|
-
@parent.declared_captures(@binding)
|
|
756
|
-
end
|
|
757
|
-
end
|
|
758
|
-
end
|
|
759
|
-
end
|
|
760
|
-
end
|