Upgrade to JRuby 1.1.3 for the scripting side of things.
| builder2.rb |
|---|
require 'compiler/bytecode'
require 'compiler/signature'
module Compiler
class ClassBuilder
import "jruby.objectweb.asm.Opcodes"
import "jruby.objectweb.asm.ClassWriter"
include Opcodes
import java.lang.Object
import java.lang.Void
include Signature
def initialize(class_name, file_name, superclass, *interfaces)
@class_name = class_name
@superclass = superclass
@class_writer = ClassWriter.new(ClassWriter::COMPUTE_MAXS)
interface_paths = []
interfaces.each {|interface| interface_paths << path(interface)}
@class_writer.visit(V1_4, ACC_PUBLIC | ACC_SUPER, class_name, nil, path(superclass), interface_paths.to_java(:string))
@class_writer.visit_source(file_name, nil)
end
def self.build(class_name, file_name, superclass = java.lang.Object, *interfaces, &block)
cb = ClassBuilder.new(class_name, file_name, superclass, *interfaces)
cb.instance_eval &block
cb.generate
end
def generate
String.from_java_bytes(@class_writer.to_byte_array)
end
def field(name, type)
@class_writer.visitField(ACC_PUBLIC, name.to_s, ci(type), nil, nil)
end
def constructor(*signature, &block)
signature.unshift Void::TYPE
MethodBuilder.build(self, ACC_PUBLIC, "<init>", signature, &block)
end
def method(name, *signature, &block)
MethodBuilder.build(self, ACC_PUBLIC, name.to_s, signature, &block)
end
def static_method(name, *signature, &block)
MethodBuilder.build(self, ACC_PUBLIC | ACC_STATIC, name.to_s, signature, &block)
end
# name for signature generation using the class being generated
def name
@class_name
end
# never generating an array
def array?
false
end
# never generating a primitive
def primitive?
false
end
def this
self
end
def new_method(modifiers, name, signature)
@class_writer.visit_method(modifiers, name, sig(*signature), nil, nil)
end
end
class MethodBuilder
include Compiler::Bytecode
attr_reader :method_visitor
def initialize(class_builder, modifiers, name, signature)
@class_builder = class_builder
@modifiers = modifiers
@name = name
@signature = signature
@method_visitor = class_builder.new_method(modifiers, name, signature)
end
def self.build(class_builder, modifiers, name, signature, &block)
mb = MethodBuilder.new(class_builder, modifiers, name, signature)
mb.start
mb.instance_eval &block
mb.stop
end
def this
@class_builder
end
end
end
Check out the code: svn co jbidwatcher/trunk/lib/ruby/site_ruby/1.8/compiler/builder2.rb
