如何通过指定其解析树来创建perl sub?

时间:2012-09-08 15:32:25

标签: perl bytecode

鉴于CODE引用,是否可以:

  1. 访问该CODE参考的分析树
  2. 通过指定CODE引用的解析树来创建新的CODE引用,该解析树可以包含 1
  3. 中返回的解析树的元素

    通常我们通过指定源代码在perl中创建子例程,然后解析源代码并将其转换为解析树。

    我想编写一个perl函数,它可以通过指定其解析树来创建子例程,并且该解析树可以从某个其他子例程的另一个解析树派生。

    可能的?

2 个答案:

答案 0 :(得分:7)

我不知道你的问题的完整答案,但我知道Data :: Dumper可以解析代码引用。查看其文档,我看到它使用B::Deparse来完成繁重的工作(B::模块是与编译器交互的模块)。不幸的是,这似乎只会导致coderef的文本表示。

相反,我在metacpan上搜索Op并获得了更多有趣的可能性。由于我现在远远超出了我最深的Perl魔法,我会留给你看看那些结果。也许某些东西会有用。

答案 1 :(得分:1)

这与操作码无关,但它确实将相同的两个变量包含在三个不同的闭包中。变量包含在子例程中,与子类get / set例程相似,然后这些封闭的变量通过其访问例程由其他闭包共享。

这是对评论的回复:我确信有必要访问解析树中的底层节点,这样我就可以创建关闭相同变量的新闭包。

use strict;
use warnings;
use v5.14;

# create closed vars
my $v1 = access_closure(6);
my $v2 = access_closure(42);

# play with them
say "v1 ", &$v1;
say "v2 ", &$v2;
say "v1 ", &$v1(5);
say "v2 ", &$v2(43);
say "v1 ", &$v1;
say "v2 ", &$v2;

# create silly closures that use them
my $test1 = test_closure(2);
my $test2 = test_closure(17);
my $test3 = test_closure(50);

# play with those
&$test1;
&$test2;
&$test3;

# create the get/set routine for a closed var
sub access_closure {
    my $val = shift;
    return sub {
        $val = shift if @_;
        return $val;
    }
}

# create a silly closure that encloses a control var and uses the two other vars
sub test_closure {
    my $val = shift;
    return sub {
        say "\nval is $val";
        printf "v1 is %2d, v2 is %2d\n",
            &$v1, &$v2;
        if (&$v1 < $val) {
            say "Increment v1";
            &$v1(&$v1+1);
        }
        if (&$v2 > $val) {
            say "Decrement v2";
            &$v2(&$v2-1);
        }
        printf "v1 is %2d, v2 is %2d\n",
            &$v1, &$v2;
    }
}