Ruby本体読みはじめた人に届けたいドキュメント

RubyKaigi2017に参加してやる気が高まったので最近は ruby/ruby のコードを読むようになってます。

github.com

しかしこれがなかなか読むのにコツがいる感じです。
RubyKaigi参加前は “Ruby under a microscope”1 を読んで「Rubyの内側面白い!!!」ってなってたのですが、実際にCのソース読みはじめると全然違いますね。マクロ多いし、C言語のこともわからんし……。
Ruby Hacking Guide こと 『Rubyソースコード完全解説』2 を読んだほうがいいのかもと悩むようになりました。

でもそんな悩みも今日解決されました。これ読めばとりあえずはRubyのレポジトリを泳げるようになりそうです。

ruby/extension.ja.rdoc at trunk · ruby/ruby · GitHub

これが非常によいです。まず読んでて面白いし噛み砕かれている感じがある。飽きずに読める感じです。
RubyKaigiに参加して Ruby 本体読むぞーって人はまずここからやってみてはいかがでしょうか。

いまだいたい25%くらい読んだのでメモった内容(というかslackログ)を以下に記しておきます。
まだまだわからんことだらけですのでこれ読んどけとか、このへんから入るのが手頃とか教えてもらえるとうれしいです〜


せっかくだからメモっておくか

INT2FIX() :: もとの整数が31bitまたは63bit以内に収まる自信
             がある時

「自信がある時」

rb_str_resize(VALUE str, long len) ::

  Rubyの文字列のサイズをlenバイトに変更する.strの長さは前
  以てセットされていなければならない.lenが元の長さよりも短
  い時は,lenバイトを越えた部分の内容は捨てられる.lenが元
  の長さよりも長い時は,元の長さを越えた部分の内容は保存さ
  れないでゴミになるだろう.この関数の呼び出しによって

“”“ゴミになるだろう”“”

さっきから思ってたんだが rb_ary_new2 とか rb_ary_new3とかあるのな

~/.g/g/h/ruby ❯❯❯ git grep rb_ary_new2 | wc -l
     123
~/.g/g/h/ruby ❯❯❯ git grep rb_ary_new3 | wc -l
     110

4まであって草

VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)

なんかしてるのかなーって思ったら定義済みの定数があるか探して、あればクラスであること、スーパークラスが同じであることを確認、なければ普通にクラスつくってからouterにassign

まあ想定どおりの動きであった

これ rb_define_class も rb_cObject に対して同じことやってね?
ああ、でも細かいところの処理違うのだな。

これらの関数の argcという引数はCの関数へ渡される引数の数(と
形式)を決めます.argcが0以上の時は関数に引き渡す引数の数を意
味します.16個以上の引数は使えません(が,要りませんよね,そ
んなに).実際の関数には先頭の引数としてselfが与えられますの
で,指定した数より1多い引数を持つことになります.

cfuncは必須引数15個までなのか

void
rb_add_method_cfunc(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc, rb_method_visibility_t visi)
{
    if (argc < -2 || 15 < argc) rb_raise(rb_eArgError, "arity out of range: %d for -2..15", argc);
argcが負の時は引数の数ではなく,形式を指定したことになります.
argcが-1の時は引数を配列に入れて渡されます.argcが-2の時は引
数はRubyの配列として渡されます.

-2のとき……

~/.g/g/h/ruby ❯❯❯ git grep 'rb_define_method.*-2'
enumerator.c:    rb_define_method(rb_cYielder, "yield", yielder_yield, -2);
enumerator.c:    rb_define_method(rb_cYielder, "<<", yielder_yield_push, -2);
ext/win32ole/win32ole_typelib.c:    rb_define_method(cWIN32OLE_TYPELIB, "initialize", foletypelib_initialize, -2);
ext/win32ole/win32ole_variant.c:    rb_define_method(cWIN32OLE_VARIANT, "initialize", folevariant_initialize, -2);
io.c:    rb_define_method(rb_cARGF, "initialize", argf_initialize, -2);
thread.c:    rb_define_method(rb_cThread, "initialize", thread_initialize, -2);

-2なんで使うのかよくわからんかった
Cの世界を通らずにそのままRuby to Rubyで動かせるからかな


  1. https://www.amazon.co.jp/dp/B01IGW56CU/Rubyのしくみ』なんだけど『言語のしくみ』と紛らわしいのでよくマイクロスコープ、アンダーアマイクロスコープと呼ばれている気がする。

  2. https://www.amazon.co.jp/dp/4844317210 中古が高いことで有名