加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

perl – 打印一个匿名子程序的代码

发布时间:2020-12-15 21:14:01 所属栏目:大数据 来源:网络整理
导读:我目前正在一个非常复杂的Perl架构,我想创建一些调试工具.由于很多行为涉及匿名子程序,我想分析一些行为,所有我需要处理的是对子程序的引用. 简而言之,是否有一种方法可以打印代码(因为Perl被解释为仍然可用?)子程序引用? 解决方法 核心模块 B::Deparse提
我目前正在一个非常复杂的Perl架构,我想创建一些调试工具.由于很多行为涉及匿名子程序,我想分析一些行为,所有我需要处理的是对子程序的引用.

简而言之,是否有一种方法可以打印代码(因为Perl被解释为仍然可用?)子程序引用?

解决方法

核心模块 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的输出中,并将导致重新编译失败.您可以使用PadWalker模块中的closed_over和set_closed_over函数来解决此问题.

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读