Perl には、コンパイル時にユーザー Perl コードを実行する BEGIN ブロックがあります。このコードは、コンパイルされる他のコードの意味に影響を与える可能性があるため、Perl の解析が「不可能」になります。
たとえば、コードは次のとおりです。
sub foo { return "OH HAI" }
本当に":
BEGIN {
*{"${package}::foo"} = sub { return "OH HAI" };
}
これは、誰かが Perl を次のように書けることを意味します:
BEGIN {
print "Hi user, type the code for foo: ";
my $code = <>;
*{"${package}::foo"} = eval $code;
}
明らかに、静的分析ツールは、ユーザーがここに入力しようとしているコードを推測できません。(また、ユーザーがsub ($) {}
の代わりにと言うと、 のsub {}
呼び出しがfoo
プログラムの残りの部分でどのように解釈されるかにさえ影響し、解析が中断される可能性があります。)
良いニュースは、不可能なケースが非常にまれであることです。技術的には可能ですが、実際のコードではほぼ確実に役に立ちません。したがって、静的分析ツールを作成している場合、これで問題が発生することはほとんどありません。
公平を期すために言うと、すべての言語にはこの問題、またはそれに類似した問題があります。例として、お気に入りのコード ウォーカーを次の Lisp コードに投げます。
(iter (for i from 1 to 10) (collect i))
iter
マクロは不透明であり、理解するには特別な知識が必要になるため、これがリストを生成するループであるとはおそらく予測できません。現実には、これは理論的には煩わしいことです (コードを実行しないと理解できないか、少なくともiter
マクロを実行すると、この入力で実行が停止することはありません) が、実際には非常に便利です (繰り返しは簡単です書くプログラマーと将来のプログラマーが読む)。
最後に、Perl には構文解析が比較的難しいため、Java にあるような静的解析ツールやリファクタリング ツールがないと多くの人が考えています。私はこれが真実であるとは思えません。その必要性はなく、誰もそれを書くことを気にしていないと思います。(人々は「リント」を必要とするので、たとえば Perl::Critic があります。)
コードを生成するために必要な Perl の静的解析 (テスト カウンターと Makefile.PL を維持するためのいくつかの emacs マクロ) は正常に機能しました。奇妙なコーナーケースが私のコードを狂わせることはありますか? もちろん、保守が不可能なコードを無理に書くつもりはありません。