O■この章でできること
B
B::Deparse
B::Lint
・Perlコンパイラバックエンドを使う
・Perlソースコードを再生成する
・Perlソースコードをチェックする
・Perlソースコードのレビュー
ここでは、Perl付属のコンパイラを使って、Perlソースコードのレビューをする方法を解説します。まず、PerlコンパイラはBというモジュールにまとめられています。Bモジュールのサブクラスとして、各種のコンパイラ関連のバックエンド機能が含まれています。
Bモジュールを使うためのユーザフロントエンドとして、Oモジュールがあります。これを使うと、コマンドラインから簡単にBモジュールの機能を使うことができます。Oモジュールを使った書式は次のようになります。
B::Deparseモジュールは、Perlソースコードをコンパイルし、その内部情報を元にソースコードを再生成します。生成させるソースは、元のソースと全く同じにはなりません。これを使うと、自分で書いたソースと、B::Deparseモジュールが生成したコードを比較して、別の表記方法や効率的な表記方法など、いろいろな発見をすることができます。
B::Deparseモジュールのオプションには次のものがあります。
では、実際に使ってみます。低水準サーバソケットで作成したPerlのソースファイルsocket_s.plを再生成してみます。コマンドラインから次のように入力します。
perl -MO=Deparse socket_s.pl > socket_s_dp.pl
元のソースは次のようになっています。
#!/usr/bin/perl ############################################# # 低水準サーバソケットのサンプル # Author: "Perl Programming Tips" ############################################# use Socket; # TCPのプロトコル番号を取得 $tcpProtoNo = getprotobyname('tcp'); # SOCKET作成 socket(HSOCK, PF_INET, SOCK_STREAM, $tcpProtoNo) || die("socket() fail:$!\n"); # パックされたネットワークアドレスを作成 $address = sockaddr_in(3000, INADDR_ANY); # ローカルマシン上のポートにバインド bind(HSOCK, $address) || die("bind() fail:$!\n"); # OSへの通知と待ち行列の最大数設定 listen(HSOCK, 1); # クライアントの接続待ち accept(HCNCT, HSOCK) || die("accept() fail:$!\n"); # メッセージ受信 if (recv(HCNCT, $message, 30, MSG_WAITALL) == undef) { die("recv() fail\n"); } print "$message\n"; # メッセージ送信 if (send(HCNCT, 'Message from server to client.', 0) == undef) { die("send() fail:$!\n"); } # SOCKETクローズ close(HSOCK);
これに対して、Deparseが生成したソースは次のようになりました。
use Socket;
$tcpProtoNo = getprotobyname 'tcp';
die "socket() fail:$!\n" unless socket HSOCK, 2, 1, $tcpProtoNo;
$address = sockaddr_in(3000, "\000\000\000\000");
die "bind() fail:$!\n" unless bind HSOCK, $address;
listen HSOCK, 1;
die "accept() fail:$!\n" unless accept HCNCT, HSOCK;
if (recv(HCNCT, $message, 30, 8) == undef) {
die "recv() fail\n";
}
print "$message\n";
if (send(HCNCT, 'Message from server to client.', 0) == undef) {
die "send() fail:$!\n";
}
close HSOCK;
だいぶ元のソースとは変わっています。もちろんDeparseが生成したソースが最適であるとは限りませんが、我流ではわからないような自分の癖などがわかってくるので参考になると思います。
次は、ソースコードをチェックする方法について解説します。まず、通常のチェックには、perlコマンドに-wオプションをつけて実行することで、warningを出力することができます。このチェック方法では、未使用の変数などがあった場合に警告が出力されます。
-wオプションではチェックされない、さらに高度なチェックをする場合は、B::Lintモジュールを使います。B::Lintモジュールのオプションには次のものがあります。
では、実際にB:Lintを使って警告を出力してみます。サンプルで作成した次のようなソース(compiler01_01.pl)をチェックしてみます。
#!/usr/bin/perl ############################################# # ソースコードチェックのサンプル # Author: "Perl Programming Tips" ############################################# @array = ("aaa", "bbb", "ccc"); $string = "abcdefghijklmn"; # スカラーコンテンキストに配列を使用 print ref(@array) . "\n"; # $_の明示的な使用 print "$_\n"; # 正規表現の後方参照用の特殊変数を使用 $string =~ s/(def)/$`/g; print "$string\n"; # 未定義のサブルーチンを使用 &sub_routine;
コマンドラインから次のように入力します。
perl -MO=Lint,all compiler01_01.pl
出力結果は次のようになります。
$perl -MO=Lint,all compiler01_ 01.pl Implicit scalar context for array in reference-type operator at compiler01_01.pl line 12 Use of $_ at compiler01_01.pl line 15 Use of regexp variable $` at compiler01_01.pl line 18 Nonexistant subroutine 'sub_routine' called at compiler01_01.pl line 21 compiler01_01.pl syntax OK $
-wオプションではチェックできない警告が出力されているのがわかります。