如何从Perl中的coderef获取语法树?

jpa*_*cek 2 perl code-analysis abstract-syntax-tree bytecode-manipulation

我想在Perl中检查和操作任意Perl程序的代码(由coderefs获取).有没有工具/模块/库?类似于B :: Concise的东西,除了B :: Concise在输出上打印代码,但我想以编程方式检查它.

我想像这样使用它.给定一个coderef F,例如.有10个参数:

$ret = &$F(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10);
Run Code Online (Sandbox Code Playgroud)

我想创建一个函数F1,st.

&$F(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10) == 
  &$F1(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10)*
  &$C(x2, x3, x4, x5, x6, x7, x8, x9, x10)
Run Code Online (Sandbox Code Playgroud)

那就是把它"分解"成两部分,第二部分不依赖于x1第一部分,第一部分尽可能简单(我假设它F是一个巨大的产品).

我想要的应用是Metropolis采样算法的优化 - 假设我正在对分布进行采样p(x1 | x2 = X1, x3 = X3, ...) = f(x1, x2, x3, ...).算法本身是不变的.乘法常数因子和其他变量不会通过算法改变,因此不依赖于x1(即$c从上面)的部分根本不需要进行评估.

联合概率可能有例如.以下表格:

  p(x1, x2, x3, x4, x5) = g1(x1, x2)*g2(x2, x3)*g3(x3, x4)*g4(x4, x5)*g5(x4, x1)*g6(x5, x1)
Run Code Online (Sandbox Code Playgroud)

我还考虑构建p一个由具有注释的因素组成的对象,其中变量是特定因素所依赖的.即使这样也会受益于代码内省(自动确定变量).

raf*_*afl 9

对于选择的内省,B通常使用模块族.

给定代码引用$cv,首先为其创建一个B对象:

my $b_cv = B::svref_2object($cv);
Run Code Online (Sandbox Code Playgroud)

现在,您可以调用其中记录的各种方法B来从optree中检索各种内容.

仅使用optree内省,您已经可以实现惊人的功能.请参阅相关DBIx::Perlish的高级示例.

还有一个B::Generate模块,允许建立新的选择,做任何你想做的事情,或操纵现有的选择.然而,B::Generate并不像人们希望的那样成熟,并且有很多缺失的功能和相当多的错误.

实际optree创建和操作通常最好使用Perl的C API进行,如记载于perlapi,perlgutsperlhack,等等.您可能还需要学习一些XS,以便将您写回的perree操作函数暴露给perl空间,但这真的很容易.

构建optrees(不一定基于其他现有的被反对的optrees)似乎最近变得有些受欢迎,特别是因为Syntax Plugins已经在perl 5.12.0中添加到核心.您可以Scope::Escape::Sugar在cpan上找到各种示例.

然而,处理perl的optrees仍然有点繁琐,并不完全适合初学者.它不应该是任何最神秘的东西.像使用B::Deparse->new->coderef2text($cv)然后可能使用评估的源代码略微修改的东西实际上就我想要从纯perl空间进行optree内省.

您可能想稍微退一步并解释您尝试解决的实际问题.也许有一个更简单的解决方案,根本不涉及搞乱选择.