我已经分离了一个案例,其中Perl在警告消息中提供了一个非常误导性的行号.我在Strawberry Perl 5.16.3中测试了以下内容.
use strict;
use warnings;
my $choice = 0;
while ($choice == 0){
#This is not numeric
$choice = '5,6,7';
if ($choice eq '-4'){
print "This isn't going to happen\n";
}
}
Run Code Online (Sandbox Code Playgroud)
运行此操作时,您将收到警告消息Argument "5,6,7" isn't numeric in numeric eq (==) at example.pl line 11.但是第11行对应的行if ($choice eq '-4'){不能引起此警告消息,因为它不包含数字比较.
实际上发生的事情似乎是Perl进入下一个比较while ($choice == 0){,但是用于警告消息的行计数器没有前进.
使这种特殊情况更糟的是,由于"坏"比较是循环条件,它实际上远离提供的线.在我的(预简化)脚本中,它距离提供的行号数百行.
这是一个错误还是解析器的一个不幸的限制?
ike*_*ami 17
存储每个运算符实例的位置将是昂贵的.作为妥协,Perl只跟踪语句的位置.它通过在每个语句的开头添加位置设置操作码来实现.该if语句是$choice == 0执行之前要启动的最后一个语句,因此警告将报告为来自该行.
$ perl -MO=Concise,-exec a.pl
1 <0> enter
2 <;> nextstate(main 3 a.pl:4) v:*,&,{,x*,x&,x$,$
3 <$> const[IV 0] s
4 <0> padsv[$choice:3,12] sRM*/LVINTRO
5 <2> sassign vKS/2
6 <;> nextstate(main 4 a.pl:6) v:*,&,{,x*,x&,x$,$ <--- Location set to line 6
7 <{> enterloop(next->k last->p redo->8) v <--- Start of while loop
l <0> padsv[$choice:3,12] s <--- $choice == 0
m <$> const[IV 0] s
n <2> eq sK/2
o <|> and(other->8) vK/1
8 <;> nextstate(main 6 a.pl:9) v:*,&,x*,x&,x$,$
9 <$> const[PV "5,6,7"] s
a <0> padsv[$choice:3,12] sRM*
b <2> sassign vKS/2
c <;> nextstate(main 6 a.pl:11) v:*,&,x*,x&,x$,$ <--- Location set to line 11
d <0> padsv[$choice:3,12] s <--- Start of if statement
e <$> const[PV "-4"] s
f <2> seq sK/2
g <|> and(other->h) vK/1
h <0> pushmark s
i <$> const[PV "This isn't going to happen\n"] s
j <@> print vK
k <0> unstack v
goto l <--- Jump back to loop expr
p <2> leaveloop vKP/2
q <@> leave[1 ref] vKP/REFC
a.pl syntax OK
Run Code Online (Sandbox Code Playgroud)
这是一个已知的限制.我不知道他们为什么不简单地nextstate在循环表达式中加入op.
mob*_*mob 12
显然,从Perl 5.008开始,解释器开始省略一个操作码,让解释器知道当前的行号.
使用极简主义脚本:
while ($choice == 0) {
$choice = '5,6,7';
}
Run Code Online (Sandbox Code Playgroud)
我们从Perl 5.6获得此输出并且B::Concise:
$ perl506 -MO=Concise badwarnline.pl
f <@> leave[t1] vKP/REFC ->(end)
1 <0> enter ->2
2 <;> nextstate(main 2 badwarnline.pl:1) v ->3
e <2> leaveloop vK/2 ->f
3 <{> enterloop(next->8 last->e redo->4) v ->a
- <1> null vK/1 ->e
d <|> and(other->4) vK/1 ->e
c <2> eq sK/2 ->d
- <1> ex-rv2sv sK/1 ->b
a <$> gvsv(*choice) s ->b
b <$> const(IV 0) s ->c
- <@> lineseq vKP ->-
4 <;> nextstate(main 1 badwarnline.pl:2) v ->5
7 <2> sassign vKS/2 ->8
5 <$> const(PV "5,6,7") s ->6
- <1> ex-rv2sv sKRM*/1 ->7
6 <$> gvsv(*choice) s ->7
8 <0> unstack v ->9
9 <;> nextstate(main 2 badwarnline.pl:1) v ->a
Run Code Online (Sandbox Code Playgroud)
和Perl v5.008的输出:
$ perl508 -MO=Concise badwarnline.pl
e <@> leave[1 ref] vKP/REFC ->(end)
1 <0> enter ->2
2 <;> nextstate(main 2 badwarnline.pl:1) v ->3
d <2> leaveloop vK/2 ->e
3 <{> enterloop(next->8 last->d redo->4) v ->9
- <1> null vK/1 ->d
c <|> and(other->4) vK/1 ->d
b <2> eq sK/2 ->c
- <1> ex-rv2sv sK/1 ->a
9 <#> gvsv[*choice] s ->a
a <$> const[IV 0] s ->b
- <@> lineseq vKP ->-
4 <;> nextstate(main 1 badwarnline.pl:2) v ->5
7 <2> sassign vKS/2 ->8
5 <$> const[PV "5,6,7"] s ->6
- <1> ex-rv2sv sKRM*/1 ->7
6 <#> gvsv[*choice] s ->7
8 <0> unstack v ->9
Run Code Online (Sandbox Code Playgroud)
这些输出之间的主要区别是5.006产生的最后一行:
9 <;> nextstate(main 2 badwarnline.pl:1) v ->a
Run Code Online (Sandbox Code Playgroud)
在5.008输出中省略.