Почему эта программа действительна? Я пытался создать синтаксическую ошибку
Я запускаю ActiveState 32-разрядный ActivePerl 5.14.2 в Windows 7. Я хотел объединиться с крюком Git pre-commit для обнаружения программ, проверяемых с синтаксическими ошибками. (Как-то мне просто удалось сделать такую плохую фиксацию.) Так что, как тестовая программа, я случайно записал это:
use strict;
use warnings;
Syntax error!
exit 0;
Тем не менее, он компилируется и выполняется без предупреждений, а уровень ошибок равен нулю при выходе. Как этот действительный синтаксис?
Ответы
Ответ 1
Perl имеет синтаксис, называемый "опознавание косвенного метода". Он позволяет
Foo->new($bar)
записывается как
new Foo $bar
Итак, это означает
Syntax error ! exit 0;
совпадает с
error->Syntax(! exit 0);
или
error->Syntax(!exit(0));
Не только это синтаксис, он не приводит к ошибке во время выполнения, потому что первое, что выполнено, exit(0)
.
Ответ 2
Я не знаю, почему, но это то, что делает Perl:
perl -MO=Deparse -w yuck
BEGIN { $^W = 1; }
use warnings;
use strict 'refs';
'error'->Syntax(!exit(0));
yuck syntax OK
Кажется, что парсер считает, что вы вызываете метод Syntax
в error
-объекте... Действительно странно!
Ответ 3
Причина, по которой вы не получаете ошибку, состоит в том, что первый выполненный код
exit(0);
Поскольку у вас не было точки с запятой в первой строке:
Syntax error!
Компилятор угадывает (неправильно), что это вызов подпрограммы с оператором not
!
. Он будет затем выполнять аргументы этой подпрограммы, которая оказывается exit(0)
, после чего программа выдает и устанавливает уровень ошибок в 0. Ничто другое не выполняется, поэтому не сообщается больше ошибок времени выполнения.
Вы заметите, что если вы измените exit(0)
на нечто вроде print "Hello world!"
, вы получите сообщение об ошибке:
Can't locate object method "Syntax" via package "error" ...
и ваш уровень ошибки будет установлен:
> echo %errorlevel%
255
Ответ 4
Как отмечалось выше, это вызвано опознаванием непрямого метода. Вы можете предупредить об этом:
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";
, чтобы заставить программу умереть (это то, что я делаю)
Ответ 5
Попробуйте 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