Ruby 1.9.0のバイトコードをいじり倒す(その3)
では、このVMLib::InstSeqTreeを使って、トレースを実現したいと思います。各ブロックの始まりと終わりにprintメソッドの呼び出しを追加して、ファイル名と行番号を入れるようにします。
require 'instruction' require 'pp' include VMLib iseq = VM::InstructionSequence.compile_file(ARGV[0]) iseqt = InstSeqTree.new(iseq) iseqt.add_code_before_block {|fname, info, no| [ [:putnil], [:putobject, "enter #{fname}:#{no}\n"], [:send, :print, 1, nil, 8, nil], [:pop] ] } iseqt.add_code_after_block {|fname, info, no| [ [:putnil], [:putobject, "leave #{fname}:#{no}\n"], [:send, :print, 1, nil, 8, nil], [:pop] ] } VM::InstructionSequence.load(iseqt.to_a).eval
これに、こんな感じの階乗を求めるプログラムを食わせると
def fact(n) p n if n == 0 then 1 else n * fact(n - 1) end end print fact(5)
こんな感じの出力になります。
c:\cygwin\usr\local\bin\ruby trace2.rb fact.rb enter fact.rb:1 enter fact.rb:2 5 enter fact.rb:2 4 enter fact.rb:2 3 enter fact.rb:2 2 enter fact.rb:2 1 enter fact.rb:2 0 leave fact.rb:6 leave fact.rb:6 leave fact.rb:6 leave fact.rb:6 leave fact.rb:6 leave fact.rb:6 120leave fact.rb:10
つづく