我在Windows 7上运行ActiveState的32位ActivePerl 5.14.2。我想用Git预提交钩子来检测有语法错误的检入程序。(不知怎么的,我就做了这么糟糕的承诺。)所以作为一个测试程序,我随机写下了这个:

use strict;
use warnings;

Syntax error!

exit 0;

但是,它编译和执行时没有警告,退出时errorlevel为零。这是如何有效的语法?


我不知道为什么,但是Perl是这样做的:

perl -MO=Deparse -w yuck
BEGIN { $^W = 1; }
use warnings;
use strict 'refs';
'error'->Syntax(!exit(0));
yuck syntax OK

似乎解析器认为您正在调用error-object上的Syntax方法…奇怪的!


Perl有一种称为“间接方法符号”的语法。它允许

Foo->new($bar)

写成

new Foo $bar

这意味着

Syntax error ! exit 0;

error->Syntax(! exit 0);

or

error->Syntax(!exit(0));

它不仅语法有效,而且不会导致运行时错误,因为首先执行的是exit(0)。


没有得到错误的原因是第一次执行的代码是错误的

exit(0);

因为第一行没有分号:

Syntax error!

编译器将(错误地)猜测这是一个带有not操作符的子例程调用!抛出。然后,它将执行该子例程的参数,该子例程恰好为exit(0),此时程序退出并将errorlevel设置为0。不执行任何其他操作,因此不再报告运行时错误。

你会注意到,如果你将exit(0)更改为print "Hello world!",你会得到一个错误:

Can't locate object method "Syntax" via package "error" ...

你的错误级别将被设置:

> echo %errorlevel%
255

如上所述,这是由间接方法调用符号引起的。你可以警告:

use strict;
use warnings;
no indirect;

Syntax error!

exit 0;

生产:

Indirect call of method "Syntax" on object "error" at - line 5.

这需要间接CPAN模块。

你也可以用不间接的“致命的”;导致程序死亡(这就是我所做的)


试试Perl 6,它似乎更容易满足您的期望:

===SORRY!=== Error while compiling synerror.p6
Negation metaoperator not followed by valid infix
at synerror.p6:1
------> Syntax error!⏏<EOL>
    expecting any of:
        infix
        infix stopper

在这篇论文中,我们的目的是回答一个长期悬而未决的问题 编程语言社区:有没有可能涂上油漆 没有创建有效的Perl?

TLDR;几乎没有