520 votes

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

J'utilise la version 32 bits d'ActiveState. ActivePerl 5.14.2 sur Windows 7. Je voulais m'amuser avec un hook pre-commit Git pour détecter les programmes qui sont archivés avec des erreurs de syntaxe. (D'une manière ou d'une autre, j'ai réussi à faire un mauvais commit.) Donc, comme programme de test, j'ai noté ceci au hasard :

use strict;
use warnings;

Syntax error!

exit 0;

Cependant, il compile et exécute sans aucun avertissement, et le niveau d'erreur est de zéro à la sortie. Comment cette syntaxe peut-elle être valide ?

135 votes

Venez-vous de prouver que taper des mots aléatoires dans perl produit des programmes qui fonctionnent ?

11 votes

@PeterM Des mots à peine aléatoires. J'ai prouvé que je ne connaissais pas assez la syntaxe Perl. Maintenant j'en sais un peu plus.

10 votes

Vous voulez probablement no indirect pour empêcher ceux-là d'arriver

569voto

ikegami Points 133140

Perl possède une syntaxe appelée "notation de méthode indirecte". Elle permet

Foo->new($bar)

s'écrit comme suit

new Foo $bar

Cela signifie donc

Syntax error ! exit 0;

est la même chose que

error->Syntax(! exit 0);

ou

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

Non seulement c'est une syntaxe valide, mais cela n'entraîne pas d'erreur d'exécution car la première chose exécutée est exit(0) .

0 votes

Bonne explication ! Mais l'opérateur not ( ! ) provoquent une erreur de syntaxe ?

1 votes

@Hassan, Pourquoi ? C'est suivi d'une expression.

1 votes

Ok, peut-être parce que je ne connais pas perl, mais dans beaucoup d'autres langages, cela ne fonctionnerait que si exit est un booléen (ou quelque chose d'autre qui peut être l'opérande de la fonction ! ), c'est-à-dire que le simple fait d'être une expression ne suffit pas.

117voto

pavel Points 2815

Je ne sais pas pourquoi, mais c'est 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 le parseur pense que vous appelez la méthode Syntax sur le error -objet... Étrange en effet !

3 votes

C'est la syntaxe d'appel de méthode indirecte. Elle fonctionne (en quelque sorte) ici parce que la fonction exit(0) est évaluée en premier, ce qui fait que le programme se termine avant de tenter de transmettre le résultat à la commande 'error'->Syntax() .

7 votes

Perl semble adopter la "syntaxe indirecte (objet)", généralement utilisée comme suit new Class au lieu de Class->new() . Pour appeler la méthode Syntax le exit est exécutée, de sorte que l'erreur d'exécution ne se produit jamais.

118 votes

Félicitations. Vous avez trouvé un programme où vous devez ajouter un point-virgule pour que la compilation échoue.

56voto

TLP Points 48922

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

exit(0);

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

Syntax error!

Le compilateur supposera (de manière incorrecte) qu'il s'agit d'un appel de sous-routine avec un paramètre not opérateur ! jeté dans. Elle exécutera ensuite les arguments de cette sous-routine, qui se trouvent être exit(0) Le programme se termine alors et le niveau d'erreur est fixé à 0. Rien d'autre n'est exécuté, et aucune autre erreur d'exécution n'est signalée.

Vous remarquerez que si vous changez exit(0) à 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

7 votes

>The compiler will guess (incorrectly) Le compilateur ne peut rien faire d'incorrect.

15 votes

Oui, c'est possible. Il peut deviner de manière incorrecte ce que l'humain voulait dire.

4 votes

L'humain est le mauvais dans l'équation. Le compilateur ne peut être que "correct" ou "cassé". Il n'a pas d'avis sur la définition du langage ou l'intention de l'utilisateur.

35voto

Mark Fowler Points 638

Comme indiqué ci-dessus, cela est dû à la notation d'appel indirect de méthodes. Vous pouvez émettre un avertissement à ce sujet :

use strict;
use warnings;
no indirect;

Syntax error!

exit 0;

Produit :

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

Pour cela, il faut module CPAN indirect .

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

0 votes

À partir de Perl 5.32, vous pouvez désactiver la fonction indirecte et vous n'avez plus besoin d'ajouter un module CPAN : use v.5:32; no feature 'indirect';

7voto

moritz Points 6295

Essayez Perl 6 il semble répondre plus facilement à 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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X