如何编写perl6宏来引用文本?

时间:2017-04-22 16:23:57

标签: macros perl6

我想在P6中创建一个宏,将其参数转换为字符串。 这是我的宏:

macro tfilter($expr) {
        quasi {
                my $str = Q ({{{$expr}}});
                filter-sub $str;   
        };
}

以下是我的称呼方式:

my @some = tfilter(age < 50);

但是,当我运行程序时,我收到错误:

Unable to parse expression in quote words; couldn't find final '>'

我该如何解决这个问题?

1 个答案:

答案 0 :(得分:9)

您的用例,通过宏将一些代码转换为字符串是非常合理的。虽然我遇到了同样的用例,但是还没有一个已建立的API(即使在我脑海中)。在以下情况下会很好:

assert a ** 2 + b ** 2 == c ** 2;

assert语句宏可以评估其表达式,如果失败,则可以将其打印出来。打印出来需要对其进行字符串化。 (事实上​​,在这种情况下,拥有文件和行信息也会很好。)

(编辑:007是一个语言实验室,可以在Perl 6中充实宏。)

现在在007中,如果你对Q对象(AST)进行字符串化,你会获得AST本身的精简对象表示,而不是它代表的代码:

$ bin/007 -e='say(~quasi { 2 + 2 })'
Q::Infix::Addition {
    identifier: Q::Identifier "infix:+",
    lhs: Q::Literal::Int 2,
    rhs: Q::Literal::Int 2
}

这比输出源代码更有意义和更直接。还要考虑这样一个事实:首先可以构建永远不是源代码的AST。 (人们应该这样做。并将这些“合成Qtrees”与程序中的自然Qtrees混合。)

所以我们正在看的是Q节点上的一个名为.source的属性。然后我们就可以做到这一点:

$ bin/007 -e='say((quasi { 2 + 2 }).source)'
 2 + 2 

(注意:还不行。)

这是一个有趣的问题.source应该为合成Qtree输出什么。它应该抛出异常吗?或者只输出<black box source>?或者尽最大努力将自己变成字符串源?

回到原来的代码,这条线让我着迷:

my $str = Q ({{{$expr}}});

这实际上是一个非常有说服力的尝试来表达你想要做的事情(将AST转换成它的字符串表示)。但我怀疑它是否会按原样运作。最后,它仍然是基于源代码作为字符串的C类思维。它的基本问题是你放置{{{$expr}}}的地方(在字符串引用环境中) )不是表达式AST能够去的地方。从AST节点类型的角度来看,它没有进行类型检查,因为表达式不是引用环境的子类型。

希望有所帮助!

(PS:退一步,我认为你通过让filter-sub接受一个字符串参数来做自己的伤害。你将对这个函数中的字符串做什么?解析它以获取信息?在这种情况下,你最好不要分析AST,而不是字符串。)

(PPS:Moritz ++ on #perl6指出age < 50中有一个不相关的语法错误需要解决.Perl 6在使用它们之前对它们的定义很挑剔;宏不会改变这个等式很多。因此,Perl 6解析器会假设age是一个你尚未声明的函数。然后它会考虑<一个开头的引号字符。最后它会感到失望的是没有>。再次,宏不会让你不需要预先声明你的变量。(虽然请参阅#159进一步讨论。)