Practice of Programming

プログラム とか Linuxとかの話題

Tie::Traceで簡単printデバッギング

tieでモジュール作るの初めてなんですが、Tie::Trace作ってみました。
0.04が最新ですが、まだCPANにインデックスされていないかも。


ある変数にどんな値が入れられていくのかを追えるものです。デバッガが面倒な時もあるってことで。使いこなしてないだけ?と言われるとその通りですが(ぉ


リファレンスが入ってきた場合は、その中を再帰的にチェックして、そのリファレンスの中に何かが入った場合も追えます(追わないことも可)。ただし、blessされているリファレンスや、tieされている変数は無視します。blessed ref は大丈夫な気がするんだけど、なんかうまくいかなかったんで。


ハッシュだったら、あるキーだけとか。その他でも、ある値だけとか、ある正規表現にマッチするものとか、コードリファレンスで真が帰ってくる場合のみとか指定できます。


基本は caller(1) の場所を教えてくれますが、どこまで遡るかの指定ができます。複数の指定もできます。


詳しくはドキュメントを...英語壊れ気味だけど、日本語もあるので...ただ英語を元に書いたら日本語も壊れ気味(ぉ


サンプルスクリプト

#!/usr/bin/perl

use Tie::Trace;
use CGI;

{
  print "Test 1 /////////////\n";
  tie my %hash, "Tie::Trace";
  test(\%hash);
}

{
  print "\n\nTest 2 /////////////\n";
  tie my %hash, "Tie::Trace", caller => [1 .. 5], debug => 'dumper';
  test(\%hash);
}

{
  print "\n\nTest 3 /////////////\n";
  tie my %hash, "Tie::Trace", use => ['scalar'], caller => [1 .. 5], debug => sub{my($self) = @_; Data::Dumper::Dumper($self->parent ? $self->parent->storage : () );};
  test(\%hash);
}

sub test{
  my $hash = shift;
  my $s;
  my $x = { hash => 1, array => [qw/a b c d e/],  scalar => \$s,};
  
  $hash->{1} = $x;
  $hash->{1}->{hash} = 3;
  
  ${$x->{scalar}} = "0000";
  
  push(@{$hash->{1}->{array}}, "array", "array2");
  
  ${$hash->{1}->{scalar}} = 10;
  
  subroutine($hash, "hogehoge");
}

sub subroutine{
  subroutine2(@_);
}

sub subroutine2{
  my($r_hash, $value) = @_;
  $r_hash->{hogehogehoge} = $value;
}

これを実行すると、下記のように表示表示されます。

Test 1 /////////////
Hash => Key: 1, Value: HASH(0x82b5820) at /home/ktat/scripts/tie-debug.pl line 29.
Hash => Key: hash, Value: 3 at /home/ktat/scripts/tie-debug.pl line 30.
Scalar => Value: 0000 at /home/ktat/scripts/tie-debug.pl line 32.
Array => Point: 5, Value: array at /home/ktat/cvs/modules/Tie-Trace/lib/Tie/Trace.pm line 229.
Array => Point: 6, Value: array2 at /home/ktat/cvs/modules/Tie-Trace/lib/Tie/Trace.pm line 229.
Scalar => Value: 10 at /home/ktat/scripts/tie-debug.pl line 36.
Hash => Key: hogehogehoge, Value: hogehoge at /home/ktat/scripts/tie-debug.pl line 47.


Test 2 /////////////
Hash => Key: 1, Value: $VAR1 = {
          'scalar' => \undef,
          'array' => [
                       'a',
                       'b',
                       'c',
                       'd',
                       'e'
                     ],
          'hash' => 1
        };
 at /home/ktat/scripts/tie-debug.pl line 15.
Hash => Key: hash, Value: $VAR1 = 3;
 at /home/ktat/scripts/tie-debug.pl line 15.
Scalar => Value: $VAR1 = '0000';
 at /home/ktat/scripts/tie-debug.pl line 15.
Array => Point: 5, Value: $VAR1 = 'array';
 at /home/ktat/scripts/tie-debug.pl line 34.
 at /home/ktat/scripts/tie-debug.pl line 15.
Array => Point: 6, Value: $VAR1 = 'array2';
 at /home/ktat/scripts/tie-debug.pl line 34.
 at /home/ktat/scripts/tie-debug.pl line 15.
Scalar => Value: $VAR1 = 10;
 at /home/ktat/scripts/tie-debug.pl line 15.
Hash => Key: hogehogehoge, Value: $VAR1 = 'hogehoge';
 at /home/ktat/scripts/tie-debug.pl line 42.
 at /home/ktat/scripts/tie-debug.pl line 38.
 at /home/ktat/scripts/tie-debug.pl line 15.


Test 3 /////////////
Scalar => Value: $VAR1 = {
          'scalar' => \'0000',
          'array' => [
                       'a',
                       'b',
                       'c',
                       'd',
                       'e'
                     ],
          'hash' => 3
        };
 at /home/ktat/scripts/tie-debug.pl line 21.
Scalar => Value: $VAR1 = {
          'scalar' => \10,
          'array' => [
                       'a',
                       'b',
                       'c',
                       'd',
                       'e',
                       'array',
                       'array2'
                     ],
          'hash' => 3
        };
 at /home/ktat/scripts/tie-debug.pl line 21.

Test 1, 2, 3 とも、オプション変えただけで、一緒のテストをしていますが、出力がいろいろと違います。
1番目は何のオプションもなしです。
2番目はvalueの値をData::Dumper::Dumperで出すようにしているのと、callerで遡る数を指定しています。
3番目は2番目に加えて、scalarに値が入れられた場合のみにしぼり、debugにコードリファレンスを指定し、親のリファレンスの中身をData::Dumper::Dumperで表示しています。


作ってる最中にひどく簡単なところに、うっかりはまって、内部メソッドのテストもちゃんと書かなきゃなぁ...って痛感しました。
テスト書いとけば、寝ぼけてても、気付ける。