ruby2java 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|