PerlでAssert

Perl5.9の時点では,assersionsと-Aコマンドラインスイッチという仕組みでCのassert(3)のようなことができるようになるはずだったらしい。しかし,そのメカニズムはPerl5.10には結局採用されなかった。
開発中はassert()が欲しい,しかし,リリース後の実行時パフォーマンスは落としたくない,というのがAssertを考えるときのジレンマというわけだ。そんななかで,CPANCapr::Assertは関数呼び出しを完全に消し去ることができるので悪くない方法だと思う。

use Carp::Assert;
assert($x > 1) if DEBUG;

DEBUGはCarp::Assertの提供する定数関数で,その値が偽ならばこの一文はコンパイル時に完全に削除される。

$ PERL_NDEBUG=0 perl -MO=Deparse -MCarp::Assert \
> -e 'assert 0 if DEBUG'
use Carp::Assert;
assert 0;
-e syntax OK
$ PERL_NDEBUG=1 perl -MO=Deparse -MCarp::Assert \
> -e 'assert 0 if DEBUG'
use Carp::Assert;
'???';
-e syntax OK
$ 

まぁ,これはこれで十分使い物になるでしょう。
しかし,これではあまりに普通でつまらない!
そこでPL_peeppハックですよ。XSからコンパイル時にOPコードツリーを走査・改変をして,assert(...)を呼び出すOP_ENTERSUB以下を消し去ることができるのでは!?…というアイデアを思いついた。