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

什么是Perl中的`null vK`?

发布时间:2020-12-16 06:21:35 所属栏目:大数据 来源:网络整理
导读:使用Perl,我有两个类似的语法, if ($a $b) { exit() }do { exit() } if ($a $b) 我相信这些应该是同一个东西,但是最上面的一个创建了一个null vK操作码, 1 null vK*/1 -- null vK的意义是什么?它有什么作用? $perl -MO=Concise -e'if ($a $b) { exit() }'8
使用Perl,我有两个类似的语法,

if ($a && $b) { exit() }
do { exit() } if ($a && $b)

我相信这些应该是同一个东西,但是最上面的一个创建了一个null vK操作码,

<1> null vK*/1 ->-

null vK的意义是什么?它有什么作用?

$perl -MO=Concise -e'if ($a && $b) { exit() }'
8  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 1 -e:1) v:{ ->3
-     <1> null vK/1 ->8
6        <|> and(other->7) vK/1 ->8
-           <1> null sK/1 ->6
4              <|> and(other->5) sK/1 ->8
-                 <1> ex-rv2sv sK/1 ->4
3                    <#> gvsv[*a] s ->4
-                 <1> ex-rv2sv sK/1 ->-
5                    <#> gvsv[*b] s ->6
-           <@> scope vK ->-
-              <;> ex-nextstate(main 3 -e:1) v ->7
7              <0> exit v* ->8
-e syntax OK

以下是经文,

$perl -MO=Concise -e'do { exit() } if ($a && $b)'
8  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 1 -e:1) v:{ ->3
-     <1> null vK/1 ->8
6        <|> and(other->7) vK/1 ->8
-           <1> null sKP/1 ->6
4              <|> and(other->5) sK/1 ->8
-                 <1> ex-rv2sv sK/1 ->4
3                    <#> gvsv[*a] s ->4
-                 <1> ex-rv2sv sK/1 ->-
5                    <#> gvsv[*b] s ->6
-           <1> null vK*/1 ->-
-              <@> scope vK ->-
-                 <;> ex-nextstate(main 2 -e:1) v ->7
7                 <0> exit v* ->8

解决方法

该行开头的“ – ”表示操作不会被执行,也可以使用perl -MO = Concise,-exec来查看.

也就是说,B :: Concise输出中的null vK …或null sK …操作码并不意味着某些操作已经被优化掉了. B :: Concise上的perldoc清楚地表明这种优化由输出中的ex表示:

Nullops appear as “ex-opname”,where opname is an op that has been
optimized away by perl. They’re displayed with a sequence-number of ‘-‘,
because they are not executed (they don’t appear in previous example),
they’re printed here because they reflect the parse.

例如:

> perl  -MO=Concise -e "$a"
4  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 1 -e:1) v:{ ->3
-     **<1> ex-rv2sv vK/1 ->4**
3        <#> gvsv[*a] s ->4

那么这些空值是什么呢?

它们是来自Perl用于解析代码的yacc语法的真正空值,并且它们从一开始就不打算执行.

在你的情况下,多余的null vk直接来自以下的BLOCK语法规则(perly.y):

termdo  :       DO term %prec UNIOP                     /* do $filename */
            { $$= dofile($2,$1);}
    |   DO block    %prec '('               /* do { code */
            { $$= newUNOP(OP_NULL,OPf_SPECIAL,op_scope($2));}
        ;

我们可以在这里看到它:

>perl -MO=Concise -e "do{}"
4  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 2 -e:1) v:{ ->3
-     <1> null vK*/1 ->4
-        <@> scope vK ->-
3           <0> stub v ->4

在其他情况下,空值来自yacc操作.
显然,这些空值用于帮助管理操作树,因为它们永远不会执行,我认为Perl开发人员不会为他们的存在而烦恼.

以下是解析布尔表达式产生的null操作示例:

>perl  -MO=Concise -e "$a||$b"
6  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 1 -e:1) v:{ ->3
-     <1> null vK/1 ->6
4        <|> or(other->5) vK/1 ->6
-           <1> ex-rv2sv sK/1 ->4
3              <#> gvsv[*a] s ->4
-           <1> ex-rv2sv vK/1 ->-
5              <#> gvsv[*b] s ->6

为什么这里为空?另一个片段有助于说清楚:

>perl -MO=Concise -e "!$a&&!$b"
7  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 1 -e:1) v:{ ->3
6     <1> not vK/1 ->7
4        <|> or(other->5) sK/1 ->6
-           <1> ex-not sK/1 ->4
-              <1> ex-rv2sv sK/1 ->-
3                 <#> gvsv[*a] s ->4
-           <1> ex-not sK/1 ->6
-              <1> ex-rv2sv sK/1 ->-
5                 <#> gvsv[*b] s ->6

似乎null vK已经不是vK.
仔细观察,我们可以看到Perl优化了!$a&&!$b进入!($a || $b)而没有(!)取代null.
事实证明,Perl总是为逻辑表达式保留父操作码,如果表达式可以用外部not来简化
Perl不会放入父操作码,否则返回null.

总结一下:由B :: Concise输出中指示的NULL操作码由优化器生成,而由null指示的NULL操作码来自语法解析器.它们都不会被执行,也不会带来任何性能损失.

(编辑:李大同)

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

    推荐文章
      热点阅读