Saturday, March 28, 2009

BiteScript 0.0.1 - A Ruby DSL for JVM Bytecode

I have finally released the first version of BiteScript, my little DSL for generating JVM bytecode. Install it as a gem with "gem install bitescript".

require 'bitescript'

include BiteScript

fb = FileBuilder.build(__FILE__) do
public_class "SimpleLoop" do
public_static_method "main", void, string[] do
aload 0
push_int 0
aaload
label :top
dup
aprintln
goto :top
returnvoid
end
end
end

fb.generate do |filename, class_builder|
File.open(filename, 'w') do |file|
file.write(class_builder.generate)
end
end

BiteScript grew out of my work on Duby. I did not want to call directly into a Java bytecode API like ASM, so I wrapped it with a nice Ruby-like layer. I also wanted the option of having blocks of bytecode look like raw assembly, but also callable as an API.

Currently only two projects I know of make use of BiteScript: Duby and the upcoming Ruby-to-Java "compiler2" in JRuby, which will also be released as a gem.

For a longer example, you can look at tool/compiler2.rb in JRuby, lib/duby/jvm/jvm_compiler.rb in Duby, or an example implementation of Fibonacci in BiteScript.

I'm open to suggestions for how to improve the API, and I'd also like to add the missing Java 5 features. The better BiteScript works, the better Duby and "compiler2" will work.

For folks interested in using BiteScript, the JVM Specification is an easy-to-read complete reference for targeting the JVM, and here is my favorite JVM opcode quickref.

6 comments:

Stephen Bannasch said...

Thanks for releasing this.

I'm following your work on compiler2 with interest also.

Some misc questions/comments:

What does line 68 in mixed_bag.rb do:

loader = JRuby.runtime.jruby_class_loader

The local variable: loader isn't referred to later.

Is there rdoc online anywhere -- I didn't see any rdoc link at the Kenai site.

When I was looking at mixed_bag.rb in Kenai I wondered about loader and clicked the "raw" link to display just the source in the browser so I could easily search for other references to 'loader' but Kenai generate headers which cause the raw file to be downloaded instead of displayed.

Stephen Bannasch said...

I don't know why I missed the subsequent reference to loader ?? -- it was three lines after the first reference:

cls = loader.define_class(name[0..-7].gsub('/', '.'), bytes.to_java_bytes)

Austin Seipp said...

So, I installed jruby using macports, giving me:

$ jruby -v
jruby 1.1.6 (ruby 1.8.6 patchlevel 114) (2009-03-29 rev 6586) [i386-java]

I then installed bitescript using the command 'sudo jgem install bitescript'

When I try to run the 'mixed_bag.rb' test though, I get:

$ jruby mixed_bag.rb
/Users/austinseipp/share/java/jruby/lib/ruby/site_ruby/1.8/builtin/java/ast.rb:49:in `const_missing': uninitialized constant BiteScript (NameError)
from bitescript.rb:3
from bitescript.rb:3:in `require'
from mixed_bag.rb:3

Any way to fix this?

Robert Fischer said...

What are the missing Java 5 features?

Charles Oliver Nutter said...

Robert Fischer: There's no support in BiteScript at the moment for defining things like enums, annotations, or generic signatures.

Austin: You probably need to add -rubygems to the JRuby command line or to the script you're testing (which would be the example scripts, so perhaps I should add them there myself).

Justin Chase said...

Isn't JRuby itself just a DSL for generating bytecode? And java itself for that matter? haha