ruby2java 0.0.1
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 +9 -0
- data/LICENSE.txt +1 -0
- data/Manifest.txt +21 -0
- data/README.txt +57 -0
- data/Rakefile +50 -0
- data/bin/ruby2java +21 -0
- data/examples/MyObjectTest.java +7 -0
- data/examples/MyObjectTest2.java +13 -0
- data/examples/annotations.rb +17 -0
- data/examples/interface_example.rb +3 -0
- data/examples/metaprogramming.rb +10 -0
- data/examples/package_example.rb +3 -0
- data/examples/ruby_main.rb +9 -0
- data/examples/simple_signatures.rb +15 -0
- data/lib/compilable.rb +5 -0
- data/lib/compilable/annotation.rb +26 -0
- data/lib/compilable/interface.rb +12 -0
- data/lib/compilable/package.rb +11 -0
- data/lib/compilable/signature.rb +61 -0
- data/lib/compiler.rb +263 -0
- data/lib/ruby2java.rb +6 -0
- metadata +88 -0
data/History.txt
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
|
data/Manifest.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
bin/ruby2java
|
2
|
+
History.txt
|
3
|
+
Manifest.txt
|
4
|
+
README.txt
|
5
|
+
Rakefile
|
6
|
+
LICENSE.txt
|
7
|
+
lib/compilable.rb
|
8
|
+
lib/compiler.rb
|
9
|
+
lib/ruby2java.rb
|
10
|
+
lib/compilable/annotation.rb
|
11
|
+
lib/compilable/interface.rb
|
12
|
+
lib/compilable/package.rb
|
13
|
+
lib/compilable/signature.rb
|
14
|
+
examples/MyObjectTest.java
|
15
|
+
examples/MyObjectTest2.java
|
16
|
+
examples/annotations.rb
|
17
|
+
examples/interface_example.rb
|
18
|
+
examples/metaprogramming.rb
|
19
|
+
examples/package_example.rb
|
20
|
+
examples/ruby_main.rb
|
21
|
+
examples/simple_signatures.rb
|
data/README.txt
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
The Ruby2Java compiler inspects the *runtime* definition of classes
|
2
|
+
to produce a normal-looking Java class. All metaprogrammed methods
|
3
|
+
are reflected on the Java class, as are runtime modifications to
|
4
|
+
those methods.
|
5
|
+
|
6
|
+
== Installation
|
7
|
+
|
8
|
+
gem install ruby2java
|
9
|
+
|
10
|
+
== How do I use it?
|
11
|
+
|
12
|
+
To create a Java class from a Ruby class, use the following command:
|
13
|
+
|
14
|
+
ruby2java RubyClass file1.rb [file2.rb ...]
|
15
|
+
|
16
|
+
The compiler will then:
|
17
|
+
|
18
|
+
1. Require in all specified files. Watch those load-time side-effects!
|
19
|
+
2. Retrieve the named Ruby class
|
20
|
+
3. Inspect the Ruby class object for "signatures" and "annotations"
|
21
|
+
methods, from which it gathers Java signature/annotation info
|
22
|
+
3a. Inspect the Ruby class object for "static_signatures" and
|
23
|
+
"static_annotations" methods, for static (class) methods
|
24
|
+
4. Generate a Java .class file for the new same-named Java class
|
25
|
+
|
26
|
+
The resulting Java class will have normal constructors and methods
|
27
|
+
and will be constructible and callable lke any other Java class.
|
28
|
+
|
29
|
+
== What do I need?
|
30
|
+
|
31
|
+
* JRuby 1.3.0RC2 or higher
|
32
|
+
|
33
|
+
== Features
|
34
|
+
|
35
|
+
* Public instance methods, static methods, and constructors
|
36
|
+
* Interface implementation
|
37
|
+
* Package specification
|
38
|
+
* Basic method annotation
|
39
|
+
|
40
|
+
== Known Issues
|
41
|
+
|
42
|
+
* All Java dependencies must be compiled and available on JRuby's
|
43
|
+
classpath for the compiler to work (since it must be able to see
|
44
|
+
those classes when generating the Java signatures/annotations).
|
45
|
+
* There is no dependency tracking between compiled Ruby classes.
|
46
|
+
If two Ruby2Java-compiled Ruby classes depend on each other for
|
47
|
+
their Java signatures, you will need them to use "Object" or some
|
48
|
+
common supertype.
|
49
|
+
* Circular dependencies are not yet supported. (implied by above)
|
50
|
+
* Extending an existing Java class is not yet supported.
|
51
|
+
* Annotations have only been cursorily tested, and may not work for
|
52
|
+
nontrivial cases.
|
53
|
+
* Because the .rb files specified are embedded in the .class, it will
|
54
|
+
be larger than the sum of all those file sizes. It also does not
|
55
|
+
provide much of an obfuscation boundary.
|
56
|
+
* There are no optimizations in place to speed the dynamic dispatch
|
57
|
+
performed by each of the generated Java methods.
|
data/Rakefile
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
#TODO Remove all unnecessary code.
|
2
|
+
|
3
|
+
require 'rake'
|
4
|
+
require 'rake/testtask'
|
5
|
+
|
6
|
+
MANIFEST = FileList['bin/*', 'History.txt', 'Manifest.txt', 'README.txt',
|
7
|
+
'Rakefile', 'LICENSE.txt', 'lib/**/*.rb', "examples/**/*.{java,rb}"]
|
8
|
+
|
9
|
+
task :default do
|
10
|
+
puts 'We\'re coming!'
|
11
|
+
end
|
12
|
+
|
13
|
+
task :spec do
|
14
|
+
require 'spec/rake/spectask'
|
15
|
+
desc 'Runs Specs'
|
16
|
+
|
17
|
+
Spec::Rake::SpecTask.new do |t|
|
18
|
+
t.spec_opts ||= []
|
19
|
+
t.spec_files = if ENV['class'].nil?
|
20
|
+
FileList['spec/**_spec.rb']
|
21
|
+
else
|
22
|
+
File.join('spec', ENV['class']+'_spec.rb')
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
file 'Manifest.txt' => :manifest
|
28
|
+
task :manifest do
|
29
|
+
File.open('Manifest.txt', 'w') {|f| MANIFEST.each {|n| f << "#{n}\n"} }
|
30
|
+
end
|
31
|
+
Rake::Task['manifest'].invoke # Always regen manifest, so Hoe has up-to-date list of files
|
32
|
+
|
33
|
+
require File.dirname(__FILE__) + '/lib/ruby2java'
|
34
|
+
begin
|
35
|
+
require 'hoe'
|
36
|
+
Hoe.new('ruby2java', Ruby2Java::VERSION) do |p| # TODO: Final name: compiler2, ruby2java, r2j2?
|
37
|
+
p.rubyforge_name = "jruby-extras"
|
38
|
+
p.url = 'http://kenai.com/projects/ruby2java/pages/Home'
|
39
|
+
p.developer 'Thomas E. Enebo', 'tom.enebo@gmail.com'
|
40
|
+
p.developer 'Charles O. Nutter', 'charles.nutter@sun.com'
|
41
|
+
p.developer 'Sergio Rodríguez Arbeo', 'serabe@gmail.com'
|
42
|
+
p.summary = 'Tool for JRuby to turn Ruby code into Java classes'
|
43
|
+
p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
|
44
|
+
p.description = p.paragraphs_of('README.txt', 0...1).join
|
45
|
+
end.spec.dependencies.delete_if { |dep| dep.name == 'hoe' }
|
46
|
+
rescue LoadError
|
47
|
+
puts 'You really need Hoe installed to be able to package this gem'
|
48
|
+
rescue => e
|
49
|
+
puts "ignoring error while loading hoe: #{e.to_s}"
|
50
|
+
end
|
data/bin/ruby2java
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'ruby2java')
|
3
|
+
|
4
|
+
if ARGV.length < 2
|
5
|
+
puts "usage: ruby2java <ruby class> <embed1.rb> [<embed2.rb> ...]"
|
6
|
+
exit 1
|
7
|
+
end
|
8
|
+
|
9
|
+
ruby_class_name = ARGV.shift
|
10
|
+
embed_files = ARGV.dup
|
11
|
+
|
12
|
+
embed_files.each do |file|
|
13
|
+
require file
|
14
|
+
end
|
15
|
+
|
16
|
+
ruby_class = eval(ruby_class_name)
|
17
|
+
|
18
|
+
java_compiler = Ruby2Java::JavaCompiler.new(embed_files[0])
|
19
|
+
java_compiler.process_class(ruby_class_name, ruby_class, ruby_class_name, *embed_files)
|
20
|
+
|
21
|
+
java_compiler.write_files
|
@@ -0,0 +1,13 @@
|
|
1
|
+
public class MyObjectTest2 {
|
2
|
+
public static void main(String[] args) {
|
3
|
+
MyObject2 obj = new MyObject2();
|
4
|
+
obj.booleanMethod(false);
|
5
|
+
obj.byteMethod((byte)1);
|
6
|
+
obj.shortMethod((short)1);
|
7
|
+
obj.charMethod((char)1);
|
8
|
+
obj.intMethod(1);
|
9
|
+
obj.longMethod(1L);
|
10
|
+
obj.floatMethod(1.0f);
|
11
|
+
obj.doubleMethod(1.0);
|
12
|
+
}
|
13
|
+
}
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class TestSomething
|
2
|
+
def test_jruby_rocks
|
3
|
+
fail unless "JRuby rocks" == "JRuby" + " " + "rocks"
|
4
|
+
end
|
5
|
+
|
6
|
+
def test_jruby_will_never_support_annotations
|
7
|
+
fail("JRuby does support annotations!") if "JRuby supports annotations"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
# Anywhere else in your project, you can turn this into a Java class
|
12
|
+
if defined? Ruby2Java
|
13
|
+
TestSomething.signature 'test_jruby_rocks', [] => nil
|
14
|
+
TestSomething.signature 'test_jruby_will_never_support_annotations', [] => nil
|
15
|
+
TestSomething.annotation 'test_jruby_rocks', org.junit.Test => nil
|
16
|
+
TestSomething.annotation 'test_jruby_will_never_support_annotations', org.junit.Test => nil
|
17
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'rbconfig'
|
2
|
+
require 'java'
|
3
|
+
|
4
|
+
class Metaprogramming
|
5
|
+
%w[boolean byte short char int long float double].each do |type|
|
6
|
+
java_type = Java.send type
|
7
|
+
eval "def #{type}Method(a); a; end"
|
8
|
+
signature "#{type}Method", [java_type] => java_type if defined? Ruby2Java
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rbconfig'
|
2
|
+
|
3
|
+
class SimpleSignatures
|
4
|
+
def helloWorld
|
5
|
+
puts "Hello from Ruby"
|
6
|
+
end
|
7
|
+
def goodbyeWorld(a)
|
8
|
+
puts a
|
9
|
+
end
|
10
|
+
|
11
|
+
if defined? Ruby2Java
|
12
|
+
signature :helloWorld, [] => Java::void
|
13
|
+
signature :goodbyeWorld, [java.lang.String] => Java::void
|
14
|
+
end
|
15
|
+
end
|
data/lib/compilable.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
class Class
|
2
|
+
def annotation(name, anno_hash = {})
|
3
|
+
name = name.to_s
|
4
|
+
annotations[name] ||= {}
|
5
|
+
anno_hash.each do |k,v|
|
6
|
+
annotations[name][k] = v
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def annotations
|
11
|
+
@annotations ||= {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def static_annotation(name, anno_hash = {})
|
15
|
+
name = name.to_s
|
16
|
+
annotations[name] ||= {}
|
17
|
+
anno_hash.each do |k,v|
|
18
|
+
static_annotations[name][k] = v
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def static_annotations
|
23
|
+
@static_annotations ||= {}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class Class
|
2
|
+
|
3
|
+
def package(*package_name)
|
4
|
+
raise ArgumentError, 'too few arguments' if package_name.empty?
|
5
|
+
# Should we raise an exception?
|
6
|
+
# Only first called is considered.
|
7
|
+
@package_name = package_name.map!{|x| x.split('.')}.flatten unless @package_name
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_reader :package_name
|
11
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'jruby/ext'
|
2
|
+
|
3
|
+
class Class
|
4
|
+
|
5
|
+
def signature(name, signature)
|
6
|
+
name = name.to_s
|
7
|
+
params = signature.keys.first
|
8
|
+
sig = Signature.new(params, signature[params])
|
9
|
+
sig_method = instance_method(name) || method(name)
|
10
|
+
if sig.fit? *(sig_method.args)
|
11
|
+
signatures[name] = [sig]
|
12
|
+
else
|
13
|
+
raise ArgumentError, "java signature does not fit ruby signature"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def signatures
|
18
|
+
@signatures ||= {}
|
19
|
+
end
|
20
|
+
|
21
|
+
def static_signature(name, signature)
|
22
|
+
name = name.to_s
|
23
|
+
params = signature.keys.first
|
24
|
+
sig = Signature.new(params, signature[params])
|
25
|
+
sig_method = begin
|
26
|
+
instance_method(name)
|
27
|
+
rescue NameError
|
28
|
+
method(name)
|
29
|
+
end
|
30
|
+
if sig.fit? *(sig_method.args)
|
31
|
+
static_signatures[name] = [sig]
|
32
|
+
else
|
33
|
+
raise ArgumentError, "java signature does not fit ruby signature"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def static_signatures
|
38
|
+
@static_signatures ||= {}
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class Signature
|
43
|
+
attr_accessor :params, :retval
|
44
|
+
|
45
|
+
def initialize(params, retval)
|
46
|
+
@params, @retval = params.dup, retval
|
47
|
+
end
|
48
|
+
|
49
|
+
# Check if a signature fits in the "arity" of a method
|
50
|
+
# should be called sig.fit? *args
|
51
|
+
# where args come from instance_method(:foo).args
|
52
|
+
def fit?(compulsory, optional, rest, block) # TODO: Check for blocks
|
53
|
+
compulsory.size <= params.size && compulsory.size + optional.size >= params.size #|| !rest.nil?
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.undefined_for_arity(arity)
|
57
|
+
params = (arity < 0) ? [IRubyObject[]] : [IRubyObject] * arity
|
58
|
+
|
59
|
+
[Signature.new(params, IRubyObject)]
|
60
|
+
end
|
61
|
+
end
|
data/lib/compiler.rb
ADDED
@@ -0,0 +1,263 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bitescript'
|
3
|
+
require File.join( File.dirname(__FILE__), 'compilable.rb')
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
module Ruby2Java
|
7
|
+
class JavaCompiler
|
8
|
+
RubyObject = org.jruby.RubyObject
|
9
|
+
RubyBasicObject = org.jruby.RubyBasicObject
|
10
|
+
Ruby = org.jruby.Ruby
|
11
|
+
RubyClass = org.jruby.RubyClass
|
12
|
+
IRubyObject = org.jruby.runtime.builtin.IRubyObject
|
13
|
+
ThreadContext = org.jruby.runtime.ThreadContext
|
14
|
+
LoadService = org.jruby.runtime.load.LoadService
|
15
|
+
JClass = java.lang.Class
|
16
|
+
JavaUtil = org.jruby.javasupport.JavaUtil
|
17
|
+
JObject = java.lang.Object
|
18
|
+
|
19
|
+
def initialize(source_name)
|
20
|
+
@file_builder = BiteScript::FileBuilder.new(source_name)
|
21
|
+
end
|
22
|
+
|
23
|
+
def write_files
|
24
|
+
@file_builder.generate do |name, builder|
|
25
|
+
FileUtils.mkdir_p File.dirname(name)
|
26
|
+
File.open(name, 'w') do |f|
|
27
|
+
f.write(builder.generate)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def process_class(ruby_class_path, ruby_class, java_name, *require_files)
|
33
|
+
@file_builder.package = ruby_class.package_name if ruby_class.package_name
|
34
|
+
|
35
|
+
cb = @file_builder.public_class(java_name, RubyObject, *ruby_class.interfaces);
|
36
|
+
|
37
|
+
# field to hold the RubyClass reference
|
38
|
+
cb.private_static_field "__ruby_class__", RubyClass
|
39
|
+
|
40
|
+
# If a require file is specified, load it in static initializer
|
41
|
+
cb.static_init do
|
42
|
+
invokestatic Ruby, "getGlobalRuntime", [Ruby]
|
43
|
+
require_files.each do |require_file|
|
44
|
+
dup
|
45
|
+
ldc File.read(require_file)
|
46
|
+
ldc require_file
|
47
|
+
invokevirtual Ruby, "executeScript", [IRubyObject, cb.string, cb.string]
|
48
|
+
pop
|
49
|
+
end
|
50
|
+
ldc ruby_class_path
|
51
|
+
invokevirtual Ruby, "getClass", [RubyClass, cb.string]
|
52
|
+
dup
|
53
|
+
putstatic this, "__ruby_class__", RubyClass
|
54
|
+
ldc this.name
|
55
|
+
invokestatic JClass, "forName", [JClass, string]
|
56
|
+
invokevirtual RubyClass, "setClassAllocator", [void, JClass]
|
57
|
+
# load the script contents into the class file
|
58
|
+
returnvoid
|
59
|
+
end
|
60
|
+
|
61
|
+
cb.public_constructor do
|
62
|
+
aload 0
|
63
|
+
invokestatic Ruby, "getGlobalRuntime", [Ruby]
|
64
|
+
getstatic this, "__ruby_class__", RubyClass
|
65
|
+
invokespecial RubyObject, "<init>", [cb.void, Ruby, RubyClass]
|
66
|
+
returnvoid
|
67
|
+
end
|
68
|
+
|
69
|
+
for method_name in ruby_class.public_instance_methods(false) do
|
70
|
+
method = ruby_class.instance_method(method_name)
|
71
|
+
signatures = if ruby_class.respond_to? :signatures
|
72
|
+
ruby_class.signatures[method_name]
|
73
|
+
else
|
74
|
+
nil
|
75
|
+
end
|
76
|
+
annotations = if ruby_class.respond_to? :annotations
|
77
|
+
ruby_class.annotations[method_name]
|
78
|
+
else
|
79
|
+
nil
|
80
|
+
end
|
81
|
+
|
82
|
+
create_method(cb, method_name, method, signatures, annotations)
|
83
|
+
end
|
84
|
+
|
85
|
+
for method_name in ruby_class.public_methods(false) do
|
86
|
+
method = ruby_class.method(method_name)
|
87
|
+
signatures = if ruby_class.respond_to? :static_signatures
|
88
|
+
ruby_class.static_signatures[method_name]
|
89
|
+
else
|
90
|
+
nil
|
91
|
+
end
|
92
|
+
annotations = if ruby_class.respond_to? :static_annotations
|
93
|
+
ruby_class.static_annotations[method_name]
|
94
|
+
else
|
95
|
+
nil
|
96
|
+
end
|
97
|
+
|
98
|
+
create_method(cb, method_name, method, signatures, annotations, :static => true)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def create_method(cb, method_name, method, signatures = nil, annotations = nil, options = {})
|
103
|
+
java_signature = true
|
104
|
+
|
105
|
+
unless signatures
|
106
|
+
signatures = Signature.undefined_for_arity(method.arity)
|
107
|
+
java_signature = false
|
108
|
+
end
|
109
|
+
|
110
|
+
for s in signatures do
|
111
|
+
if options[:static]
|
112
|
+
mb = cb.public_static_method method_name, s.retval, *(s.params)
|
113
|
+
else
|
114
|
+
mb = cb.public_method method_name, s.retval, *(s.params)
|
115
|
+
end
|
116
|
+
|
117
|
+
mb.start
|
118
|
+
|
119
|
+
if annotations && annotations.size > 0
|
120
|
+
# define annotations
|
121
|
+
annotations.each do |anno_cls, anno_data|
|
122
|
+
mb.annotate(anno_cls, true) do |anno|
|
123
|
+
anno_data.each {|k,v| anno.send(k + "=", v)} if anno_data
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# prepare receiver, context, and method name for callMethod later
|
129
|
+
options[:static] ? mb.getstatic(mb.this, "__ruby_class__", RubyClass) : mb.aload(0)
|
130
|
+
mb.dup
|
131
|
+
mb.invokeinterface IRubyObject, "getRuntime", [Ruby]
|
132
|
+
ruby_index = first_local(s.params, !options[:static])
|
133
|
+
mb.dup; mb.astore ruby_index
|
134
|
+
mb.invokevirtual Ruby, "getCurrentContext", [ThreadContext]
|
135
|
+
mb.ldc method_name
|
136
|
+
|
137
|
+
# TODO: arity-specific calling
|
138
|
+
if java_signature
|
139
|
+
java_args(mb, method, s.params, ruby_index, options)
|
140
|
+
else
|
141
|
+
ruby_args(mb, method, ruby_index, options)
|
142
|
+
end
|
143
|
+
|
144
|
+
# invoke the method dynamically
|
145
|
+
# TODO: this could have a simple inline cache
|
146
|
+
mb.invokevirtual RubyBasicObject, "callMethod", [IRubyObject, ThreadContext, mb.string, IRubyObject[]]
|
147
|
+
|
148
|
+
# return the result
|
149
|
+
if java_signature
|
150
|
+
java_return(mb, s.retval)
|
151
|
+
else
|
152
|
+
ruby_return(mb, s.retval)
|
153
|
+
end
|
154
|
+
|
155
|
+
mb.stop
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def first_local(params, instance = true)
|
160
|
+
i = instance ? 1 : 0
|
161
|
+
params.each do |param|
|
162
|
+
if param == Java::long || param == Java::double
|
163
|
+
i += 2
|
164
|
+
else
|
165
|
+
i += 1
|
166
|
+
end
|
167
|
+
end
|
168
|
+
i
|
169
|
+
end
|
170
|
+
|
171
|
+
def java_args(mb, method, params, ruby_index, options = {})
|
172
|
+
# We have a signature and need to use java integration logic
|
173
|
+
mb.ldc params.size
|
174
|
+
mb.anewarray IRubyObject
|
175
|
+
base = options[:static] ? 0 : 1
|
176
|
+
index = base
|
177
|
+
0.upto(params.size - 1) do |i|
|
178
|
+
mb.dup
|
179
|
+
mb.ldc i
|
180
|
+
mb.aload ruby_index
|
181
|
+
param_type = params[i - 1]
|
182
|
+
if [mb.boolean, mb.byte, mb.short, mb.char, mb.int].include? param_type
|
183
|
+
mb.iload index + base
|
184
|
+
mb.invokestatic JavaUtil, "convertJavaToRuby", [IRubyObject, Ruby, mb.int]
|
185
|
+
elsif mb.long == param_type
|
186
|
+
mb.lload index + base
|
187
|
+
mb.invokestatic JavaUtil, "convertJavaToRuby", [IRubyObject, Ruby, mb.long]
|
188
|
+
index += 1
|
189
|
+
elsif mb.float == param_type
|
190
|
+
mb.fload index + base
|
191
|
+
mb.invokestatic JavaUtil, "convertJavaToRuby", [IRubyObject, Ruby, mb.float]
|
192
|
+
elsif mb.double == param_type
|
193
|
+
mb.dload index + base
|
194
|
+
mb.invokestatic JavaUtil, "convertJavaToRuby", [IRubyObject, Ruby, mb.double]
|
195
|
+
index += 1
|
196
|
+
else
|
197
|
+
mb.aload index + base
|
198
|
+
mb.invokestatic JavaUtil, "convertJavaToUsableRubyObject", [IRubyObject, Ruby, mb.object]
|
199
|
+
end
|
200
|
+
mb.aastore
|
201
|
+
index += 1
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
def ruby_args(mb, method, ruby_index, options = {})
|
206
|
+
if method.arity < 0
|
207
|
+
# restarg or optarg, just pass array through
|
208
|
+
mb.aload options[:static] ? 0 : 1
|
209
|
+
else
|
210
|
+
# all normal args, box them up
|
211
|
+
mb.ldc method.arity
|
212
|
+
mb.anewarray IRubyObject
|
213
|
+
i = ruby_index;
|
214
|
+
base = options[:static] ? 0 : 1
|
215
|
+
0.upto(method.arity - 1) do |i|
|
216
|
+
mb.dup
|
217
|
+
mb.ldc i
|
218
|
+
mb.aload i + base
|
219
|
+
mb.aastore
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
def ruby_return(mb, retval)
|
225
|
+
mb.areturn
|
226
|
+
end
|
227
|
+
|
228
|
+
def java_return(mb, retval)
|
229
|
+
if mb.boolean == retval
|
230
|
+
mb.invokestatic JavaUtil, "convertRubyToJavaBoolean", [mb.boolean, IRubyObject]
|
231
|
+
mb.ireturn
|
232
|
+
elsif mb.byte == retval
|
233
|
+
mb.invokestatic JavaUtil, "convertRubyToJavaByte", [mb.byte, IRubyObject]
|
234
|
+
mb.ireturn
|
235
|
+
elsif mb.short == retval
|
236
|
+
mb.invokestatic JavaUtil, "convertRubyToJavaShort", [mb.short, IRubyObject]
|
237
|
+
mb.ireturn
|
238
|
+
elsif mb.char == retval
|
239
|
+
mb.invokestatic JavaUtil, "convertRubyToJavaChar", [mb.char, IRubyObject]
|
240
|
+
mb.ireturn
|
241
|
+
elsif mb.int == retval
|
242
|
+
mb.invokestatic JavaUtil, "convertRubyToJavaInt", [mb.int, IRubyObject]
|
243
|
+
mb.ireturn
|
244
|
+
elsif mb.long == retval
|
245
|
+
mb.invokestatic JavaUtil, "convertRubyToJavaLong", [mb.long, IRubyObject]
|
246
|
+
mb.lreturn
|
247
|
+
elsif mb.float == retval
|
248
|
+
mb.invokestatic JavaUtil, "convertRubyToJavaFloat", [mb.float, IRubyObject]
|
249
|
+
mb.freturn
|
250
|
+
elsif mb.double == retval
|
251
|
+
mb.invokestatic JavaUtil, "convertRubyToJavaDouble", [mb.double, IRubyObject]
|
252
|
+
mb.dreturn
|
253
|
+
elsif retval == mb.void || retval == nil
|
254
|
+
mb.pop
|
255
|
+
mb.returnvoid
|
256
|
+
else
|
257
|
+
mb.ldc retval
|
258
|
+
mb.invokestatic JavaUtil, "convertRubyToJava", [JObject, IRubyObject, JClass]
|
259
|
+
mb.areturn
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
data/lib/ruby2java.rb
ADDED
metadata
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
3
|
+
requirements:
|
4
|
+
- - '>='
|
5
|
+
- !ruby/object:Gem::Version
|
6
|
+
version: "0"
|
7
|
+
version:
|
8
|
+
email:
|
9
|
+
- tom.enebo@gmail.com
|
10
|
+
- charles.nutter@sun.com
|
11
|
+
- serabe@gmail.com
|
12
|
+
cert_chain: []
|
13
|
+
|
14
|
+
summary: Tool for JRuby to turn Ruby code into Java classes
|
15
|
+
post_install_message:
|
16
|
+
extra_rdoc_files:
|
17
|
+
- History.txt
|
18
|
+
- Manifest.txt
|
19
|
+
- README.txt
|
20
|
+
- LICENSE.txt
|
21
|
+
homepage: http://kenai.com/projects/ruby2java/pages/Home
|
22
|
+
signing_key:
|
23
|
+
name: ruby2java
|
24
|
+
rdoc_options:
|
25
|
+
- --main
|
26
|
+
- README.txt
|
27
|
+
rubyforge_project: jruby-extras
|
28
|
+
autorequire:
|
29
|
+
licenses: []
|
30
|
+
|
31
|
+
executables:
|
32
|
+
- ruby2java
|
33
|
+
description: |-
|
34
|
+
The Ruby2Java compiler inspects the *runtime* definition of classes
|
35
|
+
to produce a normal-looking Java class. All metaprogrammed methods
|
36
|
+
are reflected on the Java class, as are runtime modifications to
|
37
|
+
those methods.
|
38
|
+
specification_version: 3
|
39
|
+
default_executable:
|
40
|
+
files:
|
41
|
+
- bin/ruby2java
|
42
|
+
- History.txt
|
43
|
+
- Manifest.txt
|
44
|
+
- README.txt
|
45
|
+
- Rakefile
|
46
|
+
- LICENSE.txt
|
47
|
+
- lib/compilable.rb
|
48
|
+
- lib/compiler.rb
|
49
|
+
- lib/ruby2java.rb
|
50
|
+
- lib/compilable/annotation.rb
|
51
|
+
- lib/compilable/interface.rb
|
52
|
+
- lib/compilable/package.rb
|
53
|
+
- lib/compilable/signature.rb
|
54
|
+
- examples/MyObjectTest.java
|
55
|
+
- examples/MyObjectTest2.java
|
56
|
+
- examples/annotations.rb
|
57
|
+
- examples/interface_example.rb
|
58
|
+
- examples/metaprogramming.rb
|
59
|
+
- examples/package_example.rb
|
60
|
+
- examples/ruby_main.rb
|
61
|
+
- examples/simple_signatures.rb
|
62
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: "0"
|
67
|
+
version:
|
68
|
+
extensions: []
|
69
|
+
|
70
|
+
rubygems_version: 1.3.3
|
71
|
+
requirements: []
|
72
|
+
|
73
|
+
authors:
|
74
|
+
- Thomas E. Enebo
|
75
|
+
- Charles O. Nutter
|
76
|
+
- "Sergio Rodr\xc3\xadguez Arbeo"
|
77
|
+
date: 2009-05-22 05:00:00 +00:00
|
78
|
+
platform: ruby
|
79
|
+
test_files: []
|
80
|
+
|
81
|
+
version: !ruby/object:Gem::Version
|
82
|
+
version: 0.0.1
|
83
|
+
require_paths:
|
84
|
+
- lib
|
85
|
+
dependencies: []
|
86
|
+
|
87
|
+
bindir: bin
|
88
|
+
has_rdoc: true
|