精华帖 (0) :: 良好帖 (11) :: 新手帖 (0) :: 隐藏帖 (2)
|
|
---|---|
作者 | 正文 |
发表时间:2008-02-05
当他完成之后,应该是这样的一个结构: Aurum | V RubyBCL | V DynamicStruct Aurum是目前徐昊正在做的一个项目,简单的介绍可以看这里:《A very brief introduction to Aurum》 通过aurum,可以更加方便的定义新的语言。 但是,仅仅依靠aurum,只能让新设计出来的语言,运行于aurum的解释环境中,ruby就已经是够慢的解释语言了,这样的解释执行方式,可以说完全无法得到具有实用价值的语言。但是,如果可以通过aurum,将一种语言编译成Java Bytecode,那么,美好的未来就会是:“能够快速的定义,具有实用价值的,新语言!而且,各种新语言,都能够基于JVM,互联互通。” RubyBCL,现在还没有出现。仅有的灵感,来自Charles Nutter的一篇blog:《Bytecode Tools in Ruby: A Low-level DSL》。这篇blog可能无法在国内访问。转贴一点过来吧: cb = Compiler::ClassBuilder.build("MyClass", "MyClass.java") do field :list, ArrayList constructor(String, ArrayList) do aload 0 invokespecial Object, "<init>", Void::TYPE aload 0 aload 1 aload 2 invokevirtual this, :bar, [ArrayList, String, ArrayList] aload 0 swap putfield this, :list, ArrayList returnvoid end static_method(:foo, this, String) do new this dup aload 0 new ArrayList dup invokespecial ArrayList, "<init>", Void::TYPE invokespecial this, "<init>", [Void::TYPE, String, ArrayList] areturn end method(:bar, ArrayList, String, ArrayList) do aload 1 invokevirtual(String, :toLowerCase, String) aload 2 swap invokevirtual(ArrayList, :add, [Boolean::TYPE, Object]) aload 2 areturn end method(:getList, ArrayList) do aload 0 getfield this, :list, ArrayList areturn end static_method(:main, Void::TYPE, String[]) do aload 0 ldc_int 0 aaload invokestatic this, :foo, [this, String] invokevirtual this, :getList, ArrayList aprintln returnvoid end end cb.write("MyClass.class") 这样一段代码,就能够得到一个MyClass.class。这个class,也可以用下面的java代码编译得到。 import java.util.ArrayList; public class MyClass { public ArrayList list; public MyClass(String a, ArrayList b) { list = bar(a, b); } public static MyClass foo(String a) { return new MyClass(a, new ArrayList()); } public ArrayList bar(String a, ArrayList b) { b.add(a.toLowerCase()); return b; } public ArrayList getList() { return list; } public static void main(String[] args) { System.out.println(foo(args[0]).getList()); } } 非常漂亮的DSL,但是,在看过Charles Nutter放在svn里的代码之后,我才发现,这家伙太讨巧了,事实上他上面的那些DSL,最后还是利用JRuby,调用了ASM这个java类库。所以,我打算,仅仅借鉴他的DSL设计,但是却用纯粹的ruby,来实现一个生成Java Bytecode的lib。 至于DynamicStruct,要从BitStruct说起,由于ruby没有一个很方便的处理二进制文件的类库,所以我找到了bit-struct,还有一篇不错的中文介绍:《用bit-struct处理结构化(二进制)数据》 但是,后来我发现,这个bit-struct,存在绝大的问题,甚至不能仅仅在他的基础上进行修改。因为他只能支持定长的数据结构,而不是可变长度的array list,变长的string,或者switch结构。因此,只能推倒重写。 我现在的工作,就是一个初步的二进制文件读写类库的实现。 简单的看看其中的测试代码吧: require "dynamic-struct" class ClassFile<DynamicStruct u4 :magic u2 :file field_type :clsf end class Temp<DynamicStruct u2 :t_file clsf :cf field_type :temp end class Temp2<DynamicStruct u2 :t_file clsf :cf temp :ttt u1 :uu1 u2 :uu2 end a=Temp2.new a.t_file=1 a.cf.magic=2 a.cf.file=3 a.ttt.t_file=4 a.ttt.cf.magic=5 a.ttt.cf.file=6 a.uu1=444 a.uu2=888 f=open("C:\\test1.class","wb") a.write(f) f.close f = File.new("C:\\test1.class") b=Temp2.new b.read(f) f.close puts b.to_s 这个test1,基本完成了与bit-struct类似的工作。 require "dynamic-struct" class Temp<DynamicStruct string :str,1 end a=Temp.new a.str='String Test!' f=open("C:\\test2.class","wb") a.write(f) f.close f = File.new("C:\\test2.class") b=Temp.new b.read(f) f.close puts b.to_s 这是动态字符串的效果。 require "dynamic-struct" class TempArray<ArrayField size_byte 1 item_type :u2 field_type :u2array end class TempStruct<DynamicStruct u2array :ua end ts=TempStruct.new ts.ua.add(1) ts.ua.add(2) ts.ua.add(3) ts.ua[2]=4 puts ts.to_s f=open("C:\\test3.class","wb") ts.write(f) f.close f = File.new("C:\\test3.class") b=TempStruct.new b.read(f) f.close puts b.to_s 这是array list的效果。 require "dynamic-struct" class TempSwitch<SwitchField size_byte 1 item_type_list({1=>:u1,2=>:u2,3=>:u4,4=>:u8}) field_type :temps end class TempStruct<DynamicStruct temps :tus end ts=TempStruct.new u=UnsignedField.new u.field_type_name="u4" u.value=33 ts.tus.value=u puts ts.to_s f=open("C:\\test4.class","wb") ts.write(f) f.close f = File.new("C:\\test4.class") b=TempStruct.new b.read(f) f.close puts b.to_s 这是switch的效果。 附上源代码,欢迎多多批评! 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2008-02-05
刚才google搜索才发现,已经有人做了与我这个很类似的工作。而且就是JavaEye的朋友~~~
为BitStruct添加list类型 不过他这样的扩展,正如我所说的,受限于bit-struct,而无法实现真正的可变长数组~~~ |
|
返回顶楼 | |
发表时间:2008-02-09
我没有搞明白这个类库是干什么用的。从你写的测试代码来看,貌似是用来读取Java的class文件,可以从class文件当中提取Java的类结构和数据的,是这么回事吗?
那这样做的意义何在?用ruby编写Java的DSL源代码,然后再编译为class,这不是多此一举吗?我直接写Java源代码,然后编译不就可以了吗? |
|
返回顶楼 | |
发表时间:2008-02-09
按我的理解是方便地实现DSL语言并且在JVM上运行吧
|
|
返回顶楼 | |
发表时间:2008-02-09
neodoxy 写道 按我的理解是方便地实现DSL语言并且在JVM上运行吧 直接用ruby做DSL,然后用jruby来跑,不是更直接? |
|
返回顶楼 | |
发表时间:2008-02-09
JRuby之所以可能,是因为通过Antlr,将ruby语言,解释为了JVM能够理解的字节码。
而aurum,就可以认为是一个ruby版的antlr,而且,可以期待的是,借助于ruby强大的DSL能力,这个ruby的版本,会远比java的版本,更为方便好用。 因此,aurum不是一个DSL支持框架,而是任意语言的快速实现平台。 但是,aurum在开发之初,并没有考虑过有关效率的任何问题。因此,如果有一组支撑类库,能够帮助aurum,将他所能够解释出来的语言,直接编译为java的Bytecode,则这条道路,就会比antlr+asm,更为快捷。 至于读取bytecode的结构化数据,则是独立于我上面所说的需求之外的能力。毕竟我已经可能很方便的实现结构化的二进制数据写入,为什么不顺便实现一个读取呢? 让ruby,拥有对于class文件的读取、分析、修改的能力,不是也很棒吗? |
|
返回顶楼 | |
发表时间:2008-02-10
庄表伟 写道 JRuby之所以可能,是因为通过Antlr,将ruby语言,解释为了JVM能够理解的字节码。
而aurum,就可以认为是一个ruby版的antlr,而且,可以期待的是,借助于ruby强大的DSL能力,这个ruby的版本,会远比java的版本,更为方便好用。 因此,aurum不是一个DSL支持框架,而是任意语言的快速实现平台。 但是,aurum在开发之初,并没有考虑过有关效率的任何问题。因此,如果有一组支撑类库,能够帮助aurum,将他所能够解释出来的语言,直接编译为java的Bytecode,则这条道路,就会比antlr+asm,更为快捷。 至于读取bytecode的结构化数据,则是独立于我上面所说的需求之外的能力。毕竟我已经可能很方便的实现结构化的二进制数据写入,为什么不顺便实现一个读取呢? 让ruby,拥有对于class文件的读取、分析、修改的能力,不是也很棒吗? 但是没有人会通过ruby-java这个途径再去创造一种新的通用语言,我相信主要用途还是DSL方面的 |
|
返回顶楼 | |
发表时间:2008-02-15
正是我所需要的,BitStruct无法处理变长字符串已经让我抓狂了。抛开未来计划不谈,这个东东对使用ruby处理二进制是福音啊,希望老大继续发展。
|
|
返回顶楼 | |
发表时间:2008-03-12
C:\Real.java
class Real { public static void main(String[] args) throws Exception { System.out.println("Hello World!"); } } 在运行了如下一段程序之后 require 'bytecode-struct' f = File.open("C:\\Real.class","rb") b=ClassFile.new b.read(f) f.close b.constant_pool[19].value='Hello World!你好,我好,大家好!' f = File.new("D:\\Real.class","wb") b.write(f) f.close 在D:\下执行 引用 java Real
就会得到: Hello World!你好,我好,大家好! 纯ruby实现的,读写Java Class,初步实现! 源代码在: http://svn.w18.net/svn/rds/ |
|
返回顶楼 | |
发表时间:2008-03-12
补充:
不同的javac,编译出来的Class,Hello World的String,未必在第20个,所以我这段代码,不一定能够正确运行的 |
|
返回顶楼 | |