Основной модуль B :: Deparse обеспечивает эту функцию.
use B::Deparse ();
my $deparse = B::Deparse->new;
my $code = sub {print "hello, world!"};
print 'sub ', $deparse->coderef2text($code), "\n";
который печатает:
sub {
print 'hello, world!';
}
При использовании B::Deparse
важно помнить, что он возвращает декомпилированную версию скомпилированного дерева кодов операций, а не исходный текст. Это означает, что константы, арифметические выражения и другие конструкции могут быть сложены и переписаны оптимизатором.
Другая часть головоломки имеет дело с замкнутыми над лексическими переменными. Если подпрограммы, с которыми вы работаете, обращаются к каким-либо внешним лексикам, они не будут присутствовать в выводе deparse и приведут к сбою перекомпиляции. Это можно решить с помощью функций closed_over
и set_closed_over
из модуля PadWalker .
use PadWalker qw/closed_over set_closed_over/;
my $closure = do {
my $counter = 0;
sub {$counter++}
};
print $closure->(), ' ' for 1..3; # 0 1 2
print "\n";
my $pad = closed_over $closure; # hash of lexicals
# create dummy lexicals for compilation
my $copy = eval 'my ('.join(','=> keys %$pad).');'.
'sub '.$deparse->coderef2text($closure);
set_closed_over $copy, $pad; # replace dummy lexicals with real ones
print $copy->(), ' ' for 1..3; # 3 4 5
Наконец, если вы хотите узнать, где находится настоящий исходный код подпрограммы, вы можете использовать основной модуль B :
use B ();
my $meta = B::svref_2object($closure);
print "$closure at ".$meta->FILE.' line '.$meta->GV->LINE."\n";
который печатает что-то вроде:
CODE(0x28dcffc) at filename.pl line 21