[Ruby] メソッド単位でのトレース

プログラムの解析、デバックに使える、メソッド単位でのトレースモジュールを作ってみました。

Rubyメソッドは最後に評価した式が戻り値となります。したっがて戻り値をトレース(表示)するのには一工夫が必要で悩んでいましたが、ruby-list ML で良い方法を教えてもらいました 。 ありがとうございます!

Ruby では ブロック付きメソッド呼び出し が行えるので メソッドの引数と戻り値を表示するメソッドが簡単に書けてしまいます。

  • トレースモジュール
module MethodTrace

  def m_trace(*args)
    a = args.inspect
    a.sub!(/^\[/, "(").sub!(/\]$/,")")
    $stderr.print "#T ", indent(+1), caller_name(), a, "\n"
    ret = yield
    $stderr.print "#T ", indent(-1), caller_name(), " = ", ret.inspect, "\n"
    ret
  end

  private

  def caller_name
    caller(2).first.scan(/`(.*)'/).to_s
  end

  def indent(d)
    $_inspect_print_level = 0 unless $_inspect_print_level
    $_inspect_print_level -= 1 if (d < 0)
    level = "  " * $_inspect_print_level
    $_inspect_print_level += 1 if (d > 0)
    return level
  end

end

include MethodTrace
  • MethodTrace を使ったコード
require 'method_trace'

def max2(a, b)
  m_trace(a, b) {
  if (a > b)
    a
  else
    b
  end
  }
end

def max3(a, b, c)
  m_trace(a, b, c) {
  max2(a, max2(b, c))
  }
end

max3(1,2,3)
  • 実行結果
#T max3(1, 2, 3)
#T   max2(2, 3)
#T   max2 = 3
#T   max2(1, 3)
#T   max2 = 3
#T max3 = 3