This is the best test so far for a complicated decompilation. Reversal turns this:
module Hello
include SomeModule
class World < Universe
attr_accessor :name
self.attr_writer :moons
def initialize(some_thing, silly_arg = some_thing.to_s, *args)
super
@name = some_thing.to_s
end
def orbit!(optional_arg = 10, required_arg, &blk)
@moons.each do |moon|
if moon.spherical(:not_cube => true)
moon.rotate
else
moon.cubify
end
moon.revolve! :twice
class << moon
def crash_into(other_planet)
other_planet.go_boom!
end
end
yield
end
end
end
end
into this (indentation is generated by the gem):
module Hello
include(SomeModule)
class World < Universe
attr_accessor(:name)
self.attr_writer(:moons)
def initialize(some_thing, silly_arg = some_thing.to_s, *args)
super
@name = some_thing.to_s
end
def orbit!(optional_arg = 10, required_arg, &blk)
@moons.each do |moon|
if moon.spherical({:not_cube => true})
moon.rotate
else
moon.cubify
end
moon.revolve!(:twice)
class << moon
def crash_into(other_planet)
other_planet.go_boom!
end
end
yield
end
end
end
end
You will need a tiny patch to your interpreter for this to work. I will be petitioning for this to be added to Ruby 1.9.2. The patch should be applied to iseq.c.
Index: iseq.c
===================================================================
--- iseq.c (revision 26813)
+++ iseq.c (working copy)
@@ -1004,6 +1004,31 @@
}
static VALUE
+iseq_s_get_from_method(VALUE klass, VALUE body)
+{
+ VALUE ret = Qnil;
+ rb_iseq_t *iseq;
+ extern rb_iseq_t *rb_method_get_iseq(VALUE body);
+
+ rb_secure(1);
+
+ if (rb_obj_is_proc(body)) {
+ rb_proc_t *proc;
+ VALUE iseqval;
+ GetProcPtr(body, proc);
+ iseqval = proc->block.iseq->self;
+ if (RUBY_VM_NORMAL_ISEQ_P(iseqval)) {
+ ret = iseqval;
+ }
+ }
+ else if ((iseq = rb_method_get_iseq(body)) != 0) {
+ ret = iseq->self;
+ }
+
+ return ret;
+}
+
+static VALUE
iseq_s_disasm(VALUE klass, VALUE body)
{
VALUE ret = Qnil;
@@ -1498,5 +1523,6 @@
rb_define_singleton_method(rb_cISeq, "compile_option=", iseq_s_compile_option_set, 1);
rb_define_singleton_method(rb_cISeq, "disasm", iseq_s_disasm, 1);
rb_define_singleton_method(rb_cISeq, "disassemble", iseq_s_disasm, 1);
+ rb_define_singleton_method(rb_cISeq, "from_method", iseq_s_get_from_method, 1);
}
- Fork the project.
- Make your feature addition or bug fix.
- Add tests for it. This is important so I don't break it in a future version unintentionally.
- Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
- Send me a pull request. Bonus points for topic branches.
Copyright (c) 2010 Michael Edgar. See LICENSE for details.