K.Sasada's Home Page

こめんとのついか

こめんとこめんと!

message

please add long comment :).

_1(Sat)

Ruby VM advent calendar #1

もう 12 月ですね.早いものです. アドベントカレンダーというのが流行っているそうなので,ローテク(手書き)でなんか書いてみます.ネタは Ruby VM に関係する何かで埋めてみます.


VM といえば bytecode ですが,Ruby の VM でバイトコードを表現するのが RubyVM::InstructionSequence クラスのオブジェクトです.長いので ISeq とします.

さっき,preview2 に間に合わせるために急いで RubyVM::InstructionSequence.of(obj) というメソッドを作りました.何をするかというと,Proc か Method を受け取って,ISeq を返すメソッドです.

それから,ISeq#path などを作りました.ISeq がどのファイルにあったか,というのを返します.ほかにも variant がありますが,まぁ見ればわかりますよね.

これがあると,こんなテストが書けます.

  LINE_OF_HERE = __LINE__
  def test_location
    iseq = ISeq.of(method(:test_location))

    assert_equal(__FILE__, iseq.path)
    assert(/#{__FILE__}/ =~ iseq.absolute_path)
    assert_equal("test_location", iseq.label)
    assert_equal("test_location", iseq.base_label)
    assert_equal(LINE_OF_HERE+1, iseq.first_lineno)

    line = __LINE__
    iseq = ISeq.of(Proc.new{})
    assert_equal(__FILE__, iseq.path)
    assert(/#{__FILE__}/ =~ iseq.absolute_path)
    assert_equal("test_location", iseq.base_label)
    assert_equal("block in test_location", iseq.label)
    assert_equal(line+1, iseq.first_lineno)
  end

それから,次のようなコードで,現在存在する ISeq をすべて集めることができます.最終的に,ファイル名ごとに集計し,行数でソートした形で出力しています.

require 'pp'

h = Hash.new{|h, k| h[k] = []}
ObjectSpace.each_object(RubyVM::InstructionSequence){|iseq|
  h[iseq.absolute_path || iseq.path] << iseq
}

h.each{|file, iseqs|
  puts file
  pp iseqs.map{|iseq| [iseq.first_lineno, iseq.label]}.sort
}

今日はこの辺で.


多分盛大にアドベントカレンダーを勘違いしているんだろうな.


好きなだけ長いコメントをどうぞ。

お名前


back

tton 記述が使えます。YukiWikiな記述してりゃ問題ありません。

「行頭に#code」 と、「行頭に#end」 で挟むと、その間の行は pre で囲まれます。プログラムのソースを書くときに使ってください。

例:

#code

(なんかプログラム書く)

#end

リンクは

[[なまえ|http://www.example.org]]

とか

[[http://www.example.org]]

で貼れます。

$Date: 2003/04/28 10:27:51 $