[Ruby] evil-ruby

http://evil.rubyforge.org/

コンセプトはわからないけど、become とか superclass= とか
Class#as_module
こんなのないかなぁ。。。と思っていたものがここにあった。
やってることは、おそらくCでの構造体レベルでのデータを変更したりしてる(はず
だけど、dl/structを使ってrubyのみで書かれてるのがすごい。

./test/tc_*.rb 試してみた所、テストが全部通らなかった。

  • rprofile付きで実行した時と結果が代わるので、不安定なのかな。

ソースのコメント内にも FIXME memory leak と書いてある。(汗

      • -

自分でも数日前に丁度似たような目的のモジュールを書いた事があったので、
その時のコードを載せてみる。

#include "ruby.h"

static VALUE
mop_set_superclass(self, klass)
  VALUE self;
  VALUE klass;
{
  if (TYPE(klass) != T_CLASS) rb_raise(rb_eTypeError, "");
  if (RCLASS(self)->super != rb_cObject) rb_clear_cache();
  RCLASS(self)->super = klass;
  return self;
}

void
Init_mop(void)
{
  rb_mMop = rb_define_module("MetaObjectProtocol");
  rb_define_method(rb_mMop, "superclass=", mop_set_superclass, 1);
}
 ruby -rmkmf -e "create_makefile('mop')" && make
#!/usr/bin/env ruby
require 'mop.so'

Foo = Class.new{define_method("say_hello"){puts "hello, foo"}}
Bar = Class.new{define_method("say_hello"){puts "hello, bar"}}
c = Class.new(Foo).extend(MetaObjectProtocol)
o = c.new
o.say_hello # hello, foo
c.superclass = Bar # 動的にスーパークラスを変更
o.say_hello # hello, bar

superclassへの代入だけでは、
superclassを何回か変更した時にメソッド名が衝突すると、
cache内の以前のsuperclassのメソッドを呼び出してしまう事があった。
(evilのforumにもpostしてみた)