web-dev-qa-db-fra.com

Pourquoi ce programme est-il valide? J'essayais de créer une erreur de syntaxe

J'utilise la version 32 bits d'ActiveState ActivePerl 5.14.2 sous Windows 7. Je voulais manipuler un crochet de pré-validation Git pour détecter les programmes en cours d'enregistrement comportant des erreurs de syntaxe. (D'une manière ou d'une autre, j'ai juste réussi à faire un tel commit.) Donc, en tant que programme de test, j'ai noté au hasard ceci:

use strict;
use warnings;

Syntax error!

exit 0;

Cependant, il compile et exécute sans avertissements et errorlevel est égal à zéro à la sortie. Comment est cette syntaxe valide?

486
Bill Ruppert

Perl a une syntaxe appelée "notation de méthode indirecte". Il permet

Foo->new($bar)

être écrit comme

new Foo $bar

Donc ça signifie

Syntax error ! exit 0;

est le même que

error->Syntax(! exit 0);

ou

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

Non seulement cette syntaxe est valide, mais elle ne génère pas d'erreur au moment de l'exécution, car la première chose exécutée est exit(0).

534
ikegami

Je ne sais pas pourquoi, mais voici ce que Perl en fait:

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

Il semble que l'analyseur pense que vous appelez la méthode Syntax sur l'objet error- ... Etrange en effet!

109
pavel

La raison pour laquelle vous ne recevez pas d'erreur est que le premier code exécuté est

exit(0);

Parce que vous n'aviez pas de point-virgule sur la première ligne:

Syntax error!

Le compilateur devine (à tort) qu'il s'agit d'un appel à un sous-programme avec un opérateur not!. Il exécutera ensuite les arguments de ce sous-programme, qui se trouve être exit(0), moment auquel le programme se ferme et définit le niveau d'erreur sur 0. Aucune autre opération n'est exécutée. Aucune autre erreur d'exécution n'est signalée.

Vous remarquerez que si vous remplacez exit(0) par quelque chose comme print "Hello world!", Vous obtenez une erreur:

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

et votre niveau d'erreur sera défini:

> echo %errorlevel%
255
53
TLP

Comme indiqué ci-dessus, cela est dû à la notation d'appel de méthode indirecte. Vous pouvez avertir sur ceci:

use strict;
use warnings;
no indirect;

Syntax error!

exit 0;

Produit:

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

Cela nécessite le module CPAN indirect .

Vous pouvez aussi utiliser no indirect "fatal"; provoquer la mort du programme (c'est ce que je fais)

33
Mark Fowler

Essayez Perl 6 , il semble mieux répondre à vos attentes:

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