Bill Ruppert
Bill Ruppert

Reputation: 9026

Why is this program valid? I was trying to create a syntax error

I'm running ActiveState's 32 bit ActivePerl 5.14.2 on Windows 7. I wanted to mess around with a Git pre-commit hook to detect programs being checked in with syntax errors. (Somehow I just managed to do such a bad commit.) So as a test program I randomly jotted this:

use strict;
use warnings;

Syntax error!

exit 0;

However, it compiles and executes with no warnings, and errorlevel is zero on exit. How is this valid syntax?

Upvotes: 527

Views: 28237

Answers (6)

ikegami
ikegami

Reputation: 386656

Perl has a syntax called "indirect method notation". It allows

Foo->new($bar)

to be written as

new Foo $bar

So that means

Syntax error ! exit 0;

is the same as

error->Syntax(! exit 0);

or

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

Not only is it valid syntax, it doesn't result in a run-time error because the first thing executed is exit(0).


This "feature" can be disabled using any of the following:

no feature qw( indirect );  # Perl 5.32+

use v5.36;                  # Perl 5.36+

Alternatively, you can get warnings using the following:

no indirect;                # CPAN module

Upvotes: 574

Holli
Holli

Reputation: 5082

In this paper, we aim to answer a long-standing open problem in the programming languages community: is it possible to smear paint on the wall without creating valid Perl?

TLDR; Hardly

Upvotes: 4

moritz
moritz

Reputation: 12852

Try Perl 6, it seems to fulfill your expectations more readily:

===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

Upvotes: 7

Mark Fowler
Mark Fowler

Reputation: 1274

As noted above this is caused by the indirect method calling notation. You can warn on this:

use strict;
use warnings;
no indirect;

Syntax error!

exit 0;

Produces:

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

This requires the indirect CPAN module.

You can also use no indirect "fatal"; to cause the program to die (this is what I do)

Upvotes: 36

pavel
pavel

Reputation: 3508

I don't know why, but this is what Perl makes of it:

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

It seems that the parser thinks you're calling the method Syntax on the error-object... Strange indeed!

Upvotes: 119

TLP
TLP

Reputation: 67920

The reason you do not get an error is that the first executed code is

exit(0);

Because you did not have a semicolon on the first line:

Syntax error!

The compiler will guess (incorrectly) that this is a subroutine call with a not operator ! thrown in. It will then execute the arguments to this subroutine, which happens to be exit(0), at which point the program exits and sets errorlevel to 0. Nothing else is executed, so no more runtime errors are reported.

You will notice that if you change exit(0) to something like print "Hello world!" you do get an error:

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

and your error level will be set:

> echo %errorlevel%
255

Upvotes: 59

Related Questions