ありがとうございます。やはり Devel::Cover は実行時の情報をキャプチャーして活用している
Assistant
うまく動作しました!サンプルコードの概要をまとめます。
サンプルコードの解説
作成した2つのファイル
| ファイル | 目的 |
|---|---|
examples/static_logic_analyzer.pl | 基本版:単純な条件式を解析 |
examples/logic_tree_builder.pl | 発展版:論理式の木構造を構築 |
核心となる技法
1. B モジュールで OP ツリーにアクセス
use B qw(svref_2object OPf_KIDS);
my $cv = svref_2object($coderef); # コードリファレンス → B::CV
my $root = $cv->ROOT; # ルート OP を取得
2. OP ツリーの走査
sub _walk_op {
my ($self, $op) = @_;
my $name = $op->name; # "and", "or", "cond_expr" など
# 子ノードを走査
if ($op->flags & OPf_KIDS) {
for (my $kid = $op->first; $kid; $kid = $kid->sibling) {
$self->_walk_op($kid);
}
}
}
3. 論理演算子の構造
# $a && $b の OP 構造
#
# and
# ├── first: $a を評価する OP
# └── sibling: $b を評価する OP
my $left_op = $op->first;
my $right_op = $left_op->sibling;
4. B::Deparse でテキスト化
my $deparse = B::Deparse->new;
$deparse->{curcv} = $cv; # 対象の CV を設定
my $text = $deparse->deparse($op, 0); # OP → Perl コード文字列
Devel::Cover との違い
| 観点 | Devel::Cover | 今回のサンプル |
|---|---|---|
| 解析タイミング | 実行時 + 事後 | コンパイル時のみ(静的) |
| 短絡評価 | 実際の実行結果を記録 | 構造から推論 |
| カバレッジ | どのパスが実行されたか | 全パスを列挙 |
| 用途 | テストのカバレッジ計測 | 論理構造の可視化 |
拡張のアイデア
- if/unless/while の解析 -
cond_expr以外の制御構造 - 複数文の解析 - サブルーチン全体ではなく特定の式
- 短絡評価の視覚化 - 到達しないパスを
Xで表示 - CNF/DNF への変換 - 論理式の正規化
何か特定の部分を深掘りしたい、あるいは別の形式の出力が欲しいなどあれば、お知らせください。
uuid: 39b6198a-b47f-4e26-ab50-35a7411204b4