Почему эта программа действительна? Я пытался создать синтаксическую ошибку

Я запускаю 32 бит ActiveState С использованием ActivePerl 5.14.2 в Windows 7. Я хотел возиться с крючком предварительной фиксации Git, чтобы обнаружить программы, проверяемые с синтаксическими ошибками. (Каким-то образом мне удалось совершить такой плохой поступок.) Так как тестовая программа я случайно набросал это:

use strict;
use warnings;

Syntax error!

exit 0;

однако он компилируется и выполняется без предупреждений, а уровень ошибок равен нулю при выходе. Как это допустимый синтаксис?

5 ответов


Perl имеет синтаксис под названием "косвенный метод нотации". Это позволяет

Foo->new($bar)

писать так:

new Foo $bar

значит

Syntax error ! exit 0;

это то же самое, что

error->Syntax(! exit 0);

или

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

это не только допустимый синтаксис, он не приводит к ошибке во время выполнения, потому что первое, что выполняется, -exit(0).


Я не знаю, почему, но это то, что Perl делает из этого:

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

кажется, что парсер думает, что вы вызываете метод Syntax на error-объект... Действительно странно!


причина, по которой вы не получаете ошибку, заключается в том, что первый выполненный код

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.

вы также можете использовать no indirect "fatal"; чтобы заставить программу умереть (это то, что я делаю)


попробовать 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