mirah 0.0.6-java → 0.0.7-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/bin/duby +0 -0
- data/bin/dubyc +0 -0
- data/bin/dubyp +0 -0
- data/bin/jrubyp +0 -0
- data/bin/mirah +0 -0
- data/bin/mirahc +0 -0
- data/bin/mirahp +0 -0
- data/examples/fib.mirah +1 -1
- data/examples/tak.mirah +1 -1
- data/examples/wiki/war/public/javascripts/prettify.js +0 -0
- data/examples/wiki/war/public/stylesheets/prettify.css +0 -0
- data/lib/mirah/ast/intrinsics.rb +1 -1
- data/lib/mirah/ast/structure.rb +4 -1
- data/lib/mirah/class_loader.rb +35 -0
- data/lib/mirah/compilation_state.rb +28 -0
- data/lib/mirah/impl.rb +273 -0
- data/lib/mirah/jvm/types.rb +13 -1
- data/lib/mirah/version.rb +1 -1
- data/lib/mirah.rb +6 -320
- data/test/test_java_typer.rb +9 -4
- data/test/test_jvm_compiler.rb +19 -1
- metadata +5 -4
- data/examples/Dynamic.class +0 -0
- data/examples/SizeThing.class +0 -0
data/bin/duby
CHANGED
File without changes
|
data/bin/dubyc
CHANGED
File without changes
|
data/bin/dubyp
CHANGED
File without changes
|
data/bin/jrubyp
CHANGED
File without changes
|
data/bin/mirah
CHANGED
File without changes
|
data/bin/mirahc
CHANGED
File without changes
|
data/bin/mirahp
CHANGED
File without changes
|
data/examples/fib.mirah
CHANGED
data/examples/tak.mirah
CHANGED
File without changes
|
File without changes
|
data/lib/mirah/ast/intrinsics.rb
CHANGED
@@ -277,7 +277,7 @@ module Mirah::AST
|
|
277
277
|
Mirah::AST.type_factory = new_factory
|
278
278
|
ast = build_ast(name, parent, transformer)
|
279
279
|
classes = compile_ast(name, ast, transformer)
|
280
|
-
loader =
|
280
|
+
loader = Mirah::ClassLoader.new(
|
281
281
|
JRuby.runtime.jruby_class_loader, classes)
|
282
282
|
klass = loader.loadClass(name, true)
|
283
283
|
if state.save_extensions
|
data/lib/mirah/ast/structure.rb
CHANGED
@@ -188,7 +188,10 @@ module Mirah::AST
|
|
188
188
|
# find all methods which would not otherwise be on java.lang.Object
|
189
189
|
impl_methods = find_methods(klass.interfaces).select do |m|
|
190
190
|
begin
|
191
|
-
|
191
|
+
# Very cumbersome. Not sure how it got this way.
|
192
|
+
mirror = BiteScript::ASM::ClassMirror.for_name('java.lang.Object')
|
193
|
+
mtype = Mirah::JVM::Types::Type.new(mirror)
|
194
|
+
mtype.java_method m.name, *m.argument_types
|
192
195
|
rescue NameError
|
193
196
|
# not found on Object
|
194
197
|
next true
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# This is a custom classloader impl to allow loading classes with
|
2
|
+
# interdependencies by having findClass retrieve classes as needed from the
|
3
|
+
# collection of all classes generated by the target script.
|
4
|
+
module Mirah
|
5
|
+
class ClassLoader < java::security::SecureClassLoader
|
6
|
+
def initialize(parent, class_map)
|
7
|
+
super(parent)
|
8
|
+
@class_map = class_map
|
9
|
+
end
|
10
|
+
|
11
|
+
def findClass(name)
|
12
|
+
if @class_map[name]
|
13
|
+
bytes = @class_map[name].to_java_bytes
|
14
|
+
defineClass(name, bytes, 0, bytes.length)
|
15
|
+
else
|
16
|
+
raise java.lang.ClassNotFoundException.new(name)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def loadClass(name, resolve)
|
21
|
+
cls = findLoadedClass(name)
|
22
|
+
if cls == nil
|
23
|
+
if @class_map[name]
|
24
|
+
cls = findClass(name)
|
25
|
+
else
|
26
|
+
cls = super(name, false)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
resolveClass(cls) if resolve
|
31
|
+
|
32
|
+
cls
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Mirah
|
2
|
+
class CompilationState
|
3
|
+
def initialize
|
4
|
+
BiteScript.bytecode_version = BiteScript::JAVA1_5
|
5
|
+
@save_extensions = true
|
6
|
+
end
|
7
|
+
|
8
|
+
attr_accessor :verbose, :destination
|
9
|
+
attr_accessor :version_printed
|
10
|
+
attr_accessor :help_printed
|
11
|
+
attr_accessor :save_extensions
|
12
|
+
|
13
|
+
def set_jvm_version(ver_str)
|
14
|
+
case ver_str
|
15
|
+
when '1.4'
|
16
|
+
BiteScript.bytecode_version = BiteScript::JAVA1_4
|
17
|
+
when '1.5'
|
18
|
+
BiteScript.bytecode_version = BiteScript::JAVA1_5
|
19
|
+
when '1.6'
|
20
|
+
BiteScript.bytecode_version = BiteScript::JAVA1_6
|
21
|
+
when '1.7'
|
22
|
+
BiteScript.bytecode_version = BiteScript::JAVA1_7
|
23
|
+
else
|
24
|
+
$stderr.puts "invalid bytecode version specified: #{ver_str}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/mirah/impl.rb
ADDED
@@ -0,0 +1,273 @@
|
|
1
|
+
module Mirah
|
2
|
+
class Impl
|
3
|
+
def initialize
|
4
|
+
Mirah::AST.type_factory = Mirah::JVM::Types::TypeFactory.new
|
5
|
+
@running = false
|
6
|
+
end
|
7
|
+
|
8
|
+
def running?
|
9
|
+
@running
|
10
|
+
end
|
11
|
+
|
12
|
+
def run(*args)
|
13
|
+
main = nil
|
14
|
+
class_map = {}
|
15
|
+
|
16
|
+
# we're running!
|
17
|
+
@running = true
|
18
|
+
|
19
|
+
# generate all bytes for all classes
|
20
|
+
generate(args) do |outfile, builder|
|
21
|
+
bytes = builder.generate
|
22
|
+
name = builder.class_name.gsub(/\//, '.')
|
23
|
+
class_map[name] = bytes
|
24
|
+
end
|
25
|
+
|
26
|
+
# load all classes
|
27
|
+
dcl = Mirah::ClassLoader.new(JRuby.runtime.jruby_class_loader, class_map)
|
28
|
+
class_map.each do |name,|
|
29
|
+
cls = dcl.load_class(name)
|
30
|
+
# TODO: using first main; find correct one
|
31
|
+
main ||= cls.get_method("main", java::lang::String[].java_class) #rescue nil
|
32
|
+
end
|
33
|
+
|
34
|
+
# run the main method we found
|
35
|
+
if main
|
36
|
+
begin
|
37
|
+
main.invoke(nil, [args.to_java(:string)].to_java)
|
38
|
+
rescue java.lang.Exception => e
|
39
|
+
e = e.cause if e.cause
|
40
|
+
raise e
|
41
|
+
end
|
42
|
+
else
|
43
|
+
puts "No main found" unless @state.version_printed || @state.help_printed
|
44
|
+
end
|
45
|
+
rescue Mirah::InternalCompilerError => ice
|
46
|
+
Mirah.print_error(ice.message, ice.position) if ice.node
|
47
|
+
raise ice
|
48
|
+
rescue Mirah::MirahError => ex
|
49
|
+
Mirah.print_error(ex.message, ex.position)
|
50
|
+
puts ex.backtrace if @state.verbose
|
51
|
+
end
|
52
|
+
|
53
|
+
def compile(*args)
|
54
|
+
generate(args) do |filename, builder|
|
55
|
+
filename = "#{@state.destination}#{filename}"
|
56
|
+
FileUtils.mkdir_p(File.dirname(filename))
|
57
|
+
bytes = builder.generate
|
58
|
+
File.open(filename, 'wb') {|f| f.write(bytes)}
|
59
|
+
end
|
60
|
+
rescue Mirah::InternalCompilerError => ice
|
61
|
+
Mirah.print_error(ice.message, ice.position) if ice.position
|
62
|
+
puts "error on #{ice.node}(#{ice.node.object_id})"
|
63
|
+
raise ice
|
64
|
+
rescue Mirah::MirahError => ex
|
65
|
+
Mirah.print_error(ex.message, ex.position)
|
66
|
+
puts ex.backtrace if @state.verbose
|
67
|
+
end
|
68
|
+
|
69
|
+
def generate(args, &block)
|
70
|
+
process_flags!(args)
|
71
|
+
|
72
|
+
# collect all ASTs from all files
|
73
|
+
all_nodes = []
|
74
|
+
puts "Parsing..." unless running?
|
75
|
+
expand_files(args).each do |duby_file|
|
76
|
+
if duby_file == '-e'
|
77
|
+
@filename = '-e'
|
78
|
+
next
|
79
|
+
elsif @filename == '-e'
|
80
|
+
puts " <inline script>" unless running?
|
81
|
+
all_nodes << parse('-e', duby_file)
|
82
|
+
else
|
83
|
+
puts " #{duby_file}" unless running?
|
84
|
+
all_nodes << parse(duby_file)
|
85
|
+
end
|
86
|
+
@filename = nil
|
87
|
+
exit 1 if @error
|
88
|
+
end
|
89
|
+
|
90
|
+
# enter all ASTs into inference engine
|
91
|
+
puts "Inferring types..." unless running?
|
92
|
+
infer_asts(all_nodes)
|
93
|
+
|
94
|
+
# compile each AST in turn
|
95
|
+
puts "Compiling..." unless running?
|
96
|
+
all_nodes.each do |ast|
|
97
|
+
puts " #{ast.position.file}" unless running?
|
98
|
+
compile_ast(ast, &block)
|
99
|
+
end
|
100
|
+
|
101
|
+
puts "Done!" unless running?
|
102
|
+
end
|
103
|
+
|
104
|
+
def parse(*args)
|
105
|
+
process_flags!(args)
|
106
|
+
@filename = args.shift
|
107
|
+
|
108
|
+
if @filename
|
109
|
+
if @filename == '-e'
|
110
|
+
@filename = 'DashE'
|
111
|
+
src = args[0]
|
112
|
+
else
|
113
|
+
src = File.read(@filename)
|
114
|
+
end
|
115
|
+
else
|
116
|
+
print_help
|
117
|
+
exit(1)
|
118
|
+
end
|
119
|
+
begin
|
120
|
+
ast = Mirah::AST.parse_ruby(src, @filename)
|
121
|
+
# rescue org.jrubyparser.lexer.SyntaxException => ex
|
122
|
+
# Mirah.print_error(ex.message, ex.position)
|
123
|
+
# raise ex if @state.verbose
|
124
|
+
end
|
125
|
+
@transformer = Mirah::Transform::Transformer.new(@state)
|
126
|
+
Java::MirahImpl::Builtin.initialize_builtins(@transformer)
|
127
|
+
@transformer.filename = @filename
|
128
|
+
ast = @transformer.transform(ast, nil)
|
129
|
+
@transformer.errors.each do |ex|
|
130
|
+
Mirah.print_error(ex.message, ex.position)
|
131
|
+
raise ex.cause || ex if @state.verbose
|
132
|
+
end
|
133
|
+
@error = @transformer.errors.size > 0
|
134
|
+
|
135
|
+
ast
|
136
|
+
rescue Mirah::InternalCompilerError => ice
|
137
|
+
Mirah.print_error(ice.message, ice.position) if ice.node
|
138
|
+
raise ice
|
139
|
+
rescue Mirah::MirahError => ex
|
140
|
+
Mirah.print_error(ex.message, ex.position)
|
141
|
+
puts ex.backtrace if @state.verbose
|
142
|
+
end
|
143
|
+
|
144
|
+
def infer_asts(asts)
|
145
|
+
typer = Mirah::Typer::JVM.new(@transformer)
|
146
|
+
asts.each {|ast| typer.infer(ast, true) }
|
147
|
+
begin
|
148
|
+
typer.resolve(false)
|
149
|
+
ensure
|
150
|
+
puts asts.inspect if @state.verbose
|
151
|
+
|
152
|
+
failed = !typer.errors.empty?
|
153
|
+
if failed
|
154
|
+
puts "Inference Error:"
|
155
|
+
typer.errors.each do |ex|
|
156
|
+
if ex.node
|
157
|
+
Mirah.print_error(ex.message, ex.position)
|
158
|
+
else
|
159
|
+
puts ex.message
|
160
|
+
end
|
161
|
+
puts ex.backtrace if @state.verbose
|
162
|
+
end
|
163
|
+
exit 1
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def compile_ast(ast, &block)
|
169
|
+
compiler = @compiler_class.new
|
170
|
+
ast.compile(compiler, false)
|
171
|
+
compiler.generate(&block)
|
172
|
+
end
|
173
|
+
|
174
|
+
def process_flags!(args)
|
175
|
+
@state ||= Mirah::CompilationState.new
|
176
|
+
while args.length > 0 && args[0] =~ /^-/
|
177
|
+
case args[0]
|
178
|
+
when '--classpath', '-c'
|
179
|
+
args.shift
|
180
|
+
Mirah::Env.decode_paths(args.shift, $CLASSPATH)
|
181
|
+
when '--cd'
|
182
|
+
args.shift
|
183
|
+
Dir.chdir(args.shift)
|
184
|
+
when '--dest', '-d'
|
185
|
+
args.shift
|
186
|
+
@state.destination = File.join(File.expand_path(args.shift), '')
|
187
|
+
when '-e'
|
188
|
+
break
|
189
|
+
when '--explicit-packages'
|
190
|
+
args.shift
|
191
|
+
Mirah::AST::Script.explicit_packages = true
|
192
|
+
when '--help', '-h'
|
193
|
+
print_help
|
194
|
+
args.clear
|
195
|
+
when '--java', '-j'
|
196
|
+
require 'mirah/jvm/source_compiler'
|
197
|
+
@compiler_class = Mirah::Compiler::JavaSource
|
198
|
+
args.shift
|
199
|
+
when '--jvm'
|
200
|
+
args.shift
|
201
|
+
@state.set_jvm_version(args.shift)
|
202
|
+
when '-I'
|
203
|
+
args.shift
|
204
|
+
$: << args.shift
|
205
|
+
when '--plugin', '-p'
|
206
|
+
args.shift
|
207
|
+
plugin = args.shift
|
208
|
+
require "mirah/plugin/#{plugin}"
|
209
|
+
when '--verbose', '-V'
|
210
|
+
Mirah::Typer.verbose = true
|
211
|
+
Mirah::AST.verbose = true
|
212
|
+
Mirah::Compiler::JVM.verbose = true
|
213
|
+
@state.verbose = true
|
214
|
+
args.shift
|
215
|
+
when '--version', '-v'
|
216
|
+
args.shift
|
217
|
+
print_version
|
218
|
+
when '--no-save-extensions'
|
219
|
+
args.shift
|
220
|
+
@state.save_extensions = false
|
221
|
+
else
|
222
|
+
puts "unrecognized flag: " + args[0]
|
223
|
+
print_help
|
224
|
+
args.clear
|
225
|
+
end
|
226
|
+
end
|
227
|
+
@state.destination ||= File.join(File.expand_path('.'), '')
|
228
|
+
@compiler_class ||= Mirah::Compiler::JVM
|
229
|
+
end
|
230
|
+
|
231
|
+
def print_help
|
232
|
+
puts "#{$0} [flags] <files or -e SCRIPT>
|
233
|
+
-c, --classpath PATH\tAdd PATH to the Java classpath for compilation
|
234
|
+
--cd DIR\t\tSwitch to the specified DIR befor compilation
|
235
|
+
-d, --dir DIR\t\tUse DIR as the base dir for compilation, packages
|
236
|
+
-e CODE\t\tCompile or run the inline script following -e
|
237
|
+
\t\t\t (the class will be named \"DashE\")
|
238
|
+
--explicit-packages\tRequire explicit 'package' lines in source
|
239
|
+
-h, --help\t\tPrint this help message
|
240
|
+
-I DIR\t\tAdd DIR to the Ruby load path before running
|
241
|
+
-j, --java\t\tOutput .java source (compile mode only)
|
242
|
+
--jvm VERSION\t\tEmit JVM bytecode targeting specified JVM
|
243
|
+
\t\t\t version (1.4, 1.5, 1.6, 1.7)
|
244
|
+
-p, --plugin PLUGIN\trequire 'mirah/plugin/PLUGIN' before running
|
245
|
+
-v, --version\t\tPrint the version of Mirah to the console
|
246
|
+
-V, --verbose\t\tVerbose logging"
|
247
|
+
@state.help_printed = true
|
248
|
+
end
|
249
|
+
|
250
|
+
def print_version
|
251
|
+
puts "Mirah v#{Mirah::VERSION}"
|
252
|
+
@state.version_printed = true
|
253
|
+
end
|
254
|
+
|
255
|
+
def expand_files(files)
|
256
|
+
expanded = []
|
257
|
+
files.each do |filename|
|
258
|
+
if File.directory?(filename)
|
259
|
+
Dir[File.join(filename, '*')].each do |child|
|
260
|
+
if File.directory?(child)
|
261
|
+
files << child
|
262
|
+
elsif child =~ /\.(duby|mirah)$/
|
263
|
+
expanded << child
|
264
|
+
end
|
265
|
+
end
|
266
|
+
else
|
267
|
+
expanded << filename
|
268
|
+
end
|
269
|
+
end
|
270
|
+
expanded
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
data/lib/mirah/jvm/types.rb
CHANGED
@@ -336,7 +336,7 @@ module Mirah
|
|
336
336
|
class ArrayMetaType < MetaType; end
|
337
337
|
|
338
338
|
class DynamicType < Type
|
339
|
-
ObjectType = Type.new('java.lang.Object')
|
339
|
+
ObjectType = Type.new(BiteScript::ASM::ClassMirror.for_name('java.lang.Object'))
|
340
340
|
|
341
341
|
def initialize
|
342
342
|
# For naming, bytecode purposes, we are an Object
|
@@ -358,10 +358,22 @@ module Mirah
|
|
358
358
|
def jvm_type
|
359
359
|
java.lang.Object
|
360
360
|
end
|
361
|
+
|
362
|
+
def full_name
|
363
|
+
"dynamic"
|
364
|
+
end
|
361
365
|
|
362
366
|
def dynamic?
|
363
367
|
true
|
364
368
|
end
|
369
|
+
|
370
|
+
def superclass
|
371
|
+
ObjectType.superclass
|
372
|
+
end
|
373
|
+
|
374
|
+
def interfaces
|
375
|
+
ObjectType.interfaces
|
376
|
+
end
|
365
377
|
end
|
366
378
|
|
367
379
|
class TypeDefinition < Type
|
data/lib/mirah/version.rb
CHANGED
data/lib/mirah.rb
CHANGED
@@ -22,6 +22,7 @@ require 'mirah/typer'
|
|
22
22
|
require 'mirah/compiler'
|
23
23
|
require 'mirah/env'
|
24
24
|
require 'mirah/errors'
|
25
|
+
require 'mirah/class_loader'
|
25
26
|
begin
|
26
27
|
require 'bitescript'
|
27
28
|
rescue LoadError
|
@@ -31,19 +32,21 @@ end
|
|
31
32
|
require 'mirah/jvm/compiler'
|
32
33
|
require 'mirah/jvm/typer'
|
33
34
|
Dir[File.dirname(__FILE__) + "/mirah/plugin/*"].each {|file| require "#{file}" if file =~ /\.rb$/}
|
35
|
+
require 'mirah/impl'
|
36
|
+
require 'mirah/compilation_state'
|
34
37
|
require 'jruby'
|
35
38
|
|
36
39
|
module Mirah
|
37
40
|
def self.run(*args)
|
38
|
-
|
41
|
+
Impl.new.run(*args)
|
39
42
|
end
|
40
43
|
|
41
44
|
def self.compile(*args)
|
42
|
-
|
45
|
+
Impl.new.compile(*args)
|
43
46
|
end
|
44
47
|
|
45
48
|
def self.parse(*args)
|
46
|
-
|
49
|
+
Impl.new.parse(*args)
|
47
50
|
end
|
48
51
|
|
49
52
|
def self.plugins
|
@@ -85,323 +88,6 @@ module Mirah
|
|
85
88
|
end
|
86
89
|
end
|
87
90
|
end
|
88
|
-
|
89
|
-
class CompilationState
|
90
|
-
def initialize
|
91
|
-
BiteScript.bytecode_version = BiteScript::JAVA1_5
|
92
|
-
@save_extensions = true
|
93
|
-
end
|
94
|
-
|
95
|
-
attr_accessor :verbose, :destination
|
96
|
-
attr_accessor :version_printed
|
97
|
-
attr_accessor :help_printed
|
98
|
-
attr_accessor :save_extensions
|
99
|
-
|
100
|
-
def set_jvm_version(ver_str)
|
101
|
-
case ver_str
|
102
|
-
when '1.4'
|
103
|
-
BiteScript.bytecode_version = BiteScript::JAVA1_4
|
104
|
-
when '1.5'
|
105
|
-
BiteScript.bytecode_version = BiteScript::JAVA1_5
|
106
|
-
when '1.6'
|
107
|
-
BiteScript.bytecode_version = BiteScript::JAVA1_6
|
108
|
-
when '1.7'
|
109
|
-
BiteScript.bytecode_version = BiteScript::JAVA1_7
|
110
|
-
else
|
111
|
-
$stderr.puts "invalid bytecode version specified: #{ver_str}"
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
# This is a custom classloader impl to allow loading classes with
|
118
|
-
# interdependencies by having findClass retrieve classes as needed from the
|
119
|
-
# collection of all classes generated by the target script.
|
120
|
-
class MirahClassLoader < java::security::SecureClassLoader
|
121
|
-
def initialize(parent, class_map)
|
122
|
-
super(parent)
|
123
|
-
@class_map = class_map
|
124
|
-
end
|
125
|
-
|
126
|
-
def findClass(name)
|
127
|
-
if @class_map[name]
|
128
|
-
bytes = @class_map[name].to_java_bytes
|
129
|
-
defineClass(name, bytes, 0, bytes.length)
|
130
|
-
else
|
131
|
-
raise java.lang.ClassNotFoundException.new(name)
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
def loadClass(name, resolve)
|
136
|
-
cls = findLoadedClass(name)
|
137
|
-
if cls == nil
|
138
|
-
if @class_map[name]
|
139
|
-
cls = findClass(name)
|
140
|
-
else
|
141
|
-
cls = super(name, false)
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
resolveClass(cls) if resolve
|
146
|
-
|
147
|
-
cls
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
class MirahImpl
|
152
|
-
def initialize
|
153
|
-
Mirah::AST.type_factory = Mirah::JVM::Types::TypeFactory.new
|
154
|
-
end
|
155
|
-
|
156
|
-
def run(*args)
|
157
|
-
main = nil
|
158
|
-
class_map = {}
|
159
|
-
|
160
|
-
# generate all bytes for all classes
|
161
|
-
generate(args) do |outfile, builder|
|
162
|
-
bytes = builder.generate
|
163
|
-
name = builder.class_name.gsub(/\//, '.')
|
164
|
-
class_map[name] = bytes
|
165
|
-
end
|
166
|
-
|
167
|
-
# load all classes
|
168
|
-
dcl = MirahClassLoader.new(JRuby.runtime.jruby_class_loader, class_map)
|
169
|
-
class_map.each do |name,|
|
170
|
-
cls = dcl.load_class(name)
|
171
|
-
# TODO: using first main; find correct one
|
172
|
-
main ||= cls.get_method("main", java::lang::String[].java_class) #rescue nil
|
173
|
-
end
|
174
|
-
|
175
|
-
# run the main method we found
|
176
|
-
if main
|
177
|
-
begin
|
178
|
-
main.invoke(nil, [args.to_java(:string)].to_java)
|
179
|
-
rescue java.lang.Exception => e
|
180
|
-
e = e.cause if e.cause
|
181
|
-
raise e
|
182
|
-
end
|
183
|
-
else
|
184
|
-
puts "No main found" unless @state.version_printed || @state.help_printed
|
185
|
-
end
|
186
|
-
rescue Mirah::InternalCompilerError => ice
|
187
|
-
Mirah.print_error(ice.message, ice.position) if ice.node
|
188
|
-
raise ice
|
189
|
-
rescue Mirah::MirahError => ex
|
190
|
-
Mirah.print_error(ex.message, ex.position)
|
191
|
-
puts ex.backtrace if @state.verbose
|
192
|
-
end
|
193
|
-
|
194
|
-
def compile(*args)
|
195
|
-
generate(args) do |filename, builder|
|
196
|
-
filename = "#{@state.destination}#{filename}"
|
197
|
-
FileUtils.mkdir_p(File.dirname(filename))
|
198
|
-
bytes = builder.generate
|
199
|
-
File.open(filename, 'wb') {|f| f.write(bytes)}
|
200
|
-
end
|
201
|
-
rescue Mirah::InternalCompilerError => ice
|
202
|
-
Mirah.print_error(ice.message, ice.position) if ice.position
|
203
|
-
puts "error on #{ice.node}(#{ice.node.object_id})"
|
204
|
-
raise ice
|
205
|
-
rescue Mirah::MirahError => ex
|
206
|
-
Mirah.print_error(ex.message, ex.position)
|
207
|
-
puts ex.backtrace if @state.verbose
|
208
|
-
end
|
209
|
-
|
210
|
-
def generate(args, &block)
|
211
|
-
process_flags!(args)
|
212
|
-
|
213
|
-
# collect all ASTs from all files
|
214
|
-
all_nodes = []
|
215
|
-
expand_files(args).each do |duby_file|
|
216
|
-
if duby_file == '-e'
|
217
|
-
@filename = '-e'
|
218
|
-
next
|
219
|
-
elsif @filename == '-e'
|
220
|
-
all_nodes << parse('-e', duby_file)
|
221
|
-
else
|
222
|
-
all_nodes << parse(duby_file)
|
223
|
-
end
|
224
|
-
@filename = nil
|
225
|
-
exit 1 if @error
|
226
|
-
end
|
227
|
-
|
228
|
-
# enter all ASTs into inference engine
|
229
|
-
infer_asts(all_nodes)
|
230
|
-
|
231
|
-
# compile each AST in turn
|
232
|
-
all_nodes.each do |ast|
|
233
|
-
compile_ast(ast, &block)
|
234
|
-
end
|
235
|
-
end
|
236
|
-
|
237
|
-
def parse(*args)
|
238
|
-
process_flags!(args)
|
239
|
-
@filename = args.shift
|
240
|
-
|
241
|
-
if @filename
|
242
|
-
if @filename == '-e'
|
243
|
-
@filename = 'DashE'
|
244
|
-
src = args[0]
|
245
|
-
else
|
246
|
-
src = File.read(@filename)
|
247
|
-
end
|
248
|
-
else
|
249
|
-
print_help
|
250
|
-
exit(1)
|
251
|
-
end
|
252
|
-
begin
|
253
|
-
ast = Mirah::AST.parse_ruby(src, @filename)
|
254
|
-
# rescue org.jrubyparser.lexer.SyntaxException => ex
|
255
|
-
# Mirah.print_error(ex.message, ex.position)
|
256
|
-
# raise ex if @state.verbose
|
257
|
-
end
|
258
|
-
@transformer = Mirah::Transform::Transformer.new(@state)
|
259
|
-
Java::MirahImpl::Builtin.initialize_builtins(@transformer)
|
260
|
-
@transformer.filename = @filename
|
261
|
-
ast = @transformer.transform(ast, nil)
|
262
|
-
@transformer.errors.each do |ex|
|
263
|
-
Mirah.print_error(ex.message, ex.position)
|
264
|
-
raise ex.cause || ex if @state.verbose
|
265
|
-
end
|
266
|
-
@error = @transformer.errors.size > 0
|
267
|
-
|
268
|
-
ast
|
269
|
-
rescue Mirah::InternalCompilerError => ice
|
270
|
-
Mirah.print_error(ice.message, ice.position) if ice.node
|
271
|
-
raise ice
|
272
|
-
rescue Mirah::MirahError => ex
|
273
|
-
Mirah.print_error(ex.message, ex.position)
|
274
|
-
puts ex.backtrace if @state.verbose
|
275
|
-
end
|
276
|
-
|
277
|
-
def infer_asts(asts)
|
278
|
-
typer = Mirah::Typer::JVM.new(@transformer)
|
279
|
-
asts.each {|ast| typer.infer(ast, true) }
|
280
|
-
begin
|
281
|
-
typer.resolve(false)
|
282
|
-
ensure
|
283
|
-
puts asts.inspect if @state.verbose
|
284
|
-
|
285
|
-
failed = !typer.errors.empty?
|
286
|
-
if failed
|
287
|
-
puts "Inference Error:"
|
288
|
-
typer.errors.each do |ex|
|
289
|
-
if ex.node
|
290
|
-
Mirah.print_error(ex.message, ex.position)
|
291
|
-
else
|
292
|
-
puts ex.message
|
293
|
-
end
|
294
|
-
puts ex.backtrace if @state.verbose
|
295
|
-
end
|
296
|
-
exit 1
|
297
|
-
end
|
298
|
-
end
|
299
|
-
end
|
300
|
-
|
301
|
-
def compile_ast(ast, &block)
|
302
|
-
compiler = @compiler_class.new
|
303
|
-
ast.compile(compiler, false)
|
304
|
-
compiler.generate(&block)
|
305
|
-
end
|
306
|
-
|
307
|
-
def process_flags!(args)
|
308
|
-
@state ||= Mirah::CompilationState.new
|
309
|
-
while args.length > 0 && args[0] =~ /^-/
|
310
|
-
case args[0]
|
311
|
-
when '--classpath', '-c'
|
312
|
-
args.shift
|
313
|
-
Mirah::Env.decode_paths(args.shift, $CLASSPATH)
|
314
|
-
when '--cd'
|
315
|
-
args.shift
|
316
|
-
Dir.chdir(args.shift)
|
317
|
-
when '--dest', '-d'
|
318
|
-
args.shift
|
319
|
-
@state.destination = File.join(File.expand_path(args.shift), '')
|
320
|
-
when '-e'
|
321
|
-
break
|
322
|
-
when '--explicit-packages'
|
323
|
-
args.shift
|
324
|
-
Mirah::AST::Script.explicit_packages = true
|
325
|
-
when '--help', '-h'
|
326
|
-
print_help
|
327
|
-
args.clear
|
328
|
-
when '--java', '-j'
|
329
|
-
require 'mirah/jvm/source_compiler'
|
330
|
-
@compiler_class = Mirah::Compiler::JavaSource
|
331
|
-
args.shift
|
332
|
-
when '--jvm'
|
333
|
-
args.shift
|
334
|
-
@state.set_jvm_version(args.shift)
|
335
|
-
when '-I'
|
336
|
-
args.shift
|
337
|
-
$: << args.shift
|
338
|
-
when '--plugin', '-p'
|
339
|
-
args.shift
|
340
|
-
plugin = args.shift
|
341
|
-
require "mirah/plugin/#{plugin}"
|
342
|
-
when '--verbose', '-V'
|
343
|
-
Mirah::Typer.verbose = true
|
344
|
-
Mirah::AST.verbose = true
|
345
|
-
Mirah::Compiler::JVM.verbose = true
|
346
|
-
@state.verbose = true
|
347
|
-
args.shift
|
348
|
-
when '--version', '-v'
|
349
|
-
args.shift
|
350
|
-
print_version
|
351
|
-
when '--no-save-extensions'
|
352
|
-
args.shift
|
353
|
-
@state.save_extensions = false
|
354
|
-
else
|
355
|
-
puts "unrecognized flag: " + args[0]
|
356
|
-
print_help
|
357
|
-
args.clear
|
358
|
-
end
|
359
|
-
end
|
360
|
-
@state.destination ||= File.join(File.expand_path('.'), '')
|
361
|
-
@compiler_class ||= Mirah::Compiler::JVM
|
362
|
-
end
|
363
|
-
|
364
|
-
def print_help
|
365
|
-
puts "#{$0} [flags] <files or -e SCRIPT>
|
366
|
-
-c, --classpath PATH\tAdd PATH to the Java classpath for compilation
|
367
|
-
--cd DIR\t\tSwitch to the specified DIR befor compilation
|
368
|
-
-d, --dir DIR\t\tUse DIR as the base dir for compilation, packages
|
369
|
-
-e CODE\t\tCompile or run the inline script following -e
|
370
|
-
\t\t\t (the class will be named \"DashE\")
|
371
|
-
--explicit-packages\tRequire explicit 'package' lines in source
|
372
|
-
-h, --help\t\tPrint this help message
|
373
|
-
-I DIR\t\tAdd DIR to the Ruby load path before running
|
374
|
-
-j, --java\t\tOutput .java source (compile mode only)
|
375
|
-
--jvm VERSION\t\tEmit JVM bytecode targeting specified JVM
|
376
|
-
\t\t\t version (1.4, 1.5, 1.6, 1.7)
|
377
|
-
-p, --plugin PLUGIN\trequire 'mirah/plugin/PLUGIN' before running
|
378
|
-
-v, --version\t\tPrint the version of Mirah to the console
|
379
|
-
-V, --verbose\t\tVerbose logging"
|
380
|
-
@state.help_printed = true
|
381
|
-
end
|
382
|
-
|
383
|
-
def print_version
|
384
|
-
puts "Mirah v#{Mirah::VERSION}"
|
385
|
-
@state.version_printed = true
|
386
|
-
end
|
387
|
-
|
388
|
-
def expand_files(files)
|
389
|
-
expanded = []
|
390
|
-
files.each do |filename|
|
391
|
-
if File.directory?(filename)
|
392
|
-
Dir[File.join(filename, '*')].each do |child|
|
393
|
-
if File.directory?(child)
|
394
|
-
files << child
|
395
|
-
elsif child =~ /\.(duby|mirah)$/
|
396
|
-
expanded << child
|
397
|
-
end
|
398
|
-
end
|
399
|
-
else
|
400
|
-
expanded << filename
|
401
|
-
end
|
402
|
-
end
|
403
|
-
expanded
|
404
|
-
end
|
405
91
|
end
|
406
92
|
|
407
93
|
if __FILE__ == $0
|
data/test/test_java_typer.rb
CHANGED
@@ -16,10 +16,7 @@
|
|
16
16
|
$:.unshift File.join(File.dirname(__FILE__),'..','lib')
|
17
17
|
|
18
18
|
require 'test/unit'
|
19
|
-
require 'mirah
|
20
|
-
require 'mirah/plugin/java'
|
21
|
-
require 'mirah/jvm/compiler'
|
22
|
-
require 'mirah/jvm/typer'
|
19
|
+
require 'mirah'
|
23
20
|
|
24
21
|
class TestJavaTyper < Test::Unit::TestCase
|
25
22
|
include Mirah
|
@@ -205,4 +202,12 @@ class TestJavaTyper < Test::Unit::TestCase
|
|
205
202
|
ast = AST.parse("#{1 << 33}")
|
206
203
|
assert_equal(AST.type(nil, 'long'), ast.infer(@typer, true))
|
207
204
|
end
|
205
|
+
|
206
|
+
def test_dynamic_assignability
|
207
|
+
ast = AST.parse("a = 1; a = dynamic('foo')")
|
208
|
+
assert_equal :error, ast.infer(@typer, true).name
|
209
|
+
|
210
|
+
ast = AST.parse("a = Object.new; a = dynamic('foo')")
|
211
|
+
assert_equal 'java.lang.Object', ast.infer(@typer, true).name
|
212
|
+
end
|
208
213
|
end
|
data/test/test_jvm_compiler.rb
CHANGED
@@ -82,7 +82,7 @@ class TestJVMCompiler < Test::Unit::TestCase
|
|
82
82
|
compiler = Compiler::JVM.new
|
83
83
|
compiler.compile(ast)
|
84
84
|
classes = {}
|
85
|
-
loader =
|
85
|
+
loader = Mirah::ClassLoader.new(JRuby.runtime.jruby_class_loader, classes)
|
86
86
|
compiler.generate do |name, builder|
|
87
87
|
bytes = builder.generate
|
88
88
|
FileUtils.mkdir_p(File.dirname(name))
|
@@ -2056,6 +2056,24 @@ class TestJVMCompiler < Test::Unit::TestCase
|
|
2056
2056
|
end
|
2057
2057
|
end
|
2058
2058
|
|
2059
|
+
def test_block_with_abstract_from_object
|
2060
|
+
# Comparator interface also defines equals(Object) as abstract,
|
2061
|
+
# but it can be inherited from Object. We test that here.
|
2062
|
+
cls, = compile(<<-EOF)
|
2063
|
+
import java.util.ArrayList
|
2064
|
+
import java.util.Collections
|
2065
|
+
list = ArrayList.new(["a", "ABC", "Cats", "b"])
|
2066
|
+
Collections.sort(list) do |a, b|
|
2067
|
+
String(a).compareToIgnoreCase(String(b))
|
2068
|
+
end
|
2069
|
+
list.each {|x| puts x}
|
2070
|
+
EOF
|
2071
|
+
|
2072
|
+
assert_output("a\nABC\nb\nCats\n") do
|
2073
|
+
cls.main(nil)
|
2074
|
+
end
|
2075
|
+
end
|
2076
|
+
|
2059
2077
|
def test_each
|
2060
2078
|
cls, = compile(<<-EOF)
|
2061
2079
|
def foo
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: mirah
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.0.
|
5
|
+
version: 0.0.7
|
6
6
|
platform: java
|
7
7
|
authors:
|
8
8
|
- Charles Oliver Nutter
|
@@ -11,7 +11,7 @@ autorequire:
|
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
13
|
|
14
|
-
date: 2011-03-20
|
14
|
+
date: 2011-03-20 17:08:55.863000 -05:00
|
15
15
|
default_executable:
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
@@ -61,9 +61,12 @@ files:
|
|
61
61
|
- lib/mirah_task.rb
|
62
62
|
- lib/mirah/appengine_tasks.rb
|
63
63
|
- lib/mirah/ast.rb
|
64
|
+
- lib/mirah/class_loader.rb
|
65
|
+
- lib/mirah/compilation_state.rb
|
64
66
|
- lib/mirah/compiler.rb
|
65
67
|
- lib/mirah/env.rb
|
66
68
|
- lib/mirah/errors.rb
|
69
|
+
- lib/mirah/impl.rb
|
67
70
|
- lib/mirah/transform.rb
|
68
71
|
- lib/mirah/transform2.rb
|
69
72
|
- lib/mirah/typer.rb
|
@@ -113,7 +116,6 @@ files:
|
|
113
116
|
- test/test_typer.rb
|
114
117
|
- examples/bintrees.mirah
|
115
118
|
- examples/construction.mirah
|
116
|
-
- examples/Dynamic.class
|
117
119
|
- examples/dynamic.mirah
|
118
120
|
- examples/edb.mirah
|
119
121
|
- examples/fib.mirah
|
@@ -121,7 +123,6 @@ files:
|
|
121
123
|
- examples/fractal.mirah
|
122
124
|
- examples/java_thing.mirah
|
123
125
|
- examples/simple_class.mirah
|
124
|
-
- examples/SizeThing.class
|
125
126
|
- examples/sort_closure.mirah
|
126
127
|
- examples/swing.mirah
|
127
128
|
- examples/tak.mirah
|
data/examples/Dynamic.class
DELETED
Binary file
|
data/examples/SizeThing.class
DELETED
Binary file
|