1

给定一个类似的命令,

perl -MO=Deparse -E'use constant FOO => 42; print FOO()'

如何禁用常量折叠,这样

print 42;

给我看

print FOO();

或之类的。理想情况下,我希望这是一个适用于所有 Perl 的编译器选项。你可以在 perl 邮件列表的这个线程中看到这个话题,[perl #97942] [PATCH] 添加-DO选项以禁用优化并禁用常量折叠和使用时的窥孔优化器。. 我试过-DO了,但没有用。如果该选项不起作用,我愿意接受变通办法,但它们可能会出现。

4

2 回答 2

3

常量将自己呈现为 subs。你可以用 sub 做的事情:

  • 将其称为函数 ( FOO, FOO())
  • 在覆盖原型时将其作为函数调用 ( &FOO())
  • 在继承时将其作为函数调用@_( &FOO)
  • 将其称为方法 ( __PACKAGE__->FOO)
  • 创建对它的引用(\&FOO, *FOO{CODE}。也是*FOO需要代码 ref 的地方。)

只有第一个被折叠。因此,您可以使用

$ perl -MO=Concise,-exec -E'use constant FOO=>42; say &FOO()' 2>&1 | grep FOO
5  <#> gv[*FOO] s
$ perl -MO=Concise,-exec -E'use constant FOO=>42; say &FOO' 2>&1 | grep FOO
5  <#> gv[*FOO] s
$ perl -MO=Concise,-exec -E'use constant FOO=>42; say __PACKAGE__->FOO' 2>&1 | grep FOO
6  <.> method_named[PV "FOO"] l
$ perl -MO=Concise,-exec -E'use constant FOO=>42; say+ (\&FOO)->()' 2>&1 | grep FOO
5  <#> gv[*FOO] s
$ perl -MO=Concise,-exec -E'use constant FOO=>42; say *FOO{CODE}->()' 2>&1 | grep FOO
5  <#> gv[*FOO] s
$ perl -MO=Concise,-exec -E'use constant FOO=>42; say *FOO->()' 2>&1 | grep FOO
5  <#> gv[*FOO] s
于 2021-02-04T03:50:11.367 回答
1

您可以做的一种方法是在常量前面加上&,

perl -MO=Deparse -E'use constant FOO => 42; print &FOO()'

从文档开始perldoc perlsub

常量函数 具有“()”原型的函数是内联的潜在候选对象。如果优化和常量折叠后的结果是常量或没有其他引用的词法范围标量,那么它将用于代替没有&. 使用的调用&永远不会内联。

于 2021-02-04T01:57:11.630 回答