9
votes

Perl peut-il être "statiquement" analysé?

Un L'article appelé "Perl ne peut pas être analysé, une preuve formelle" fait le tour. Donc, Perl décidera-t-il de la signification de son code analysé au "temps d'exécution" ou "compilée"?

Dans certaines discussions que j'ai lues, j'ai l'impression que les arguments proviennent de la terminologie imprécise, alors essayez de définir vos termes techniques de votre réponse. J'ai délibérément non défini "l'heure d'exécution", "statiquement" ou "analysée" afin que je puisse obtenir des perspectives de personnes qui définissent peut-être ces termes différemment pour moi.

EDIT:

Cela ne concerne pas une analyse statique. C'est une question théorique sur le comportement de Perl.


6 commentaires

modernérlbooks.com/mt/2009/08/on- analyse-perl-5.html


Et maintenant, aussi modernérlbooks.com/ MT / 2009/08 / Comment-a-Perl-5-program-works.ht ml


Robert P: "Le modèle d'exécution de Perl 5 [est] définitivement pas identique à la notion traditionnelle d'un interprète.". Puis il continue à décrire un interprète traditionnel ...


Aussi de Hacker News: News.ycomminator.com/item?id=770072


@ Paul Biggar: une partie de celle-ci est semblable à un interprète traditionnel. La partie où elle enfreint dans l'exécution avant de finir l'interprétation du reste du code n'est pas.


@ROBERT P: Cela n'a rien à voir avec interprétation, c'est juste une fonctionnalité de langue. Vous pouvez aussi bien dire que ce n'est pas un interprète traditionnel, car il utilise $ _ (ou choisissez une fonctionnalité).


5 Réponses :


11
votes

Perl a commencé les blocs, qui exécute le code Perl de l'utilisateur au moment de la compilation. Ce code peut affecter la signification de l'autre code à compiler, ce qui le rend "impossible" à analyser Perl.

Par exemple, le code: xxx

est "vraiment ": xxx

Cela signifie que quelqu'un pourrait écrire Perl comme: xxx

évidemment, aucun outil d'analyse statique ne peut deviner quoi Code L'utilisateur va taper ici. (Et si l'utilisateur dit sub ($) {} au lieu de sub {} , il affectera même la manière dont les appels vers FOO sont interprétés Le reste du programme, éteignant potentiellement l'analyse.)

La bonne nouvelle est que les cas impossibles sont très cassés; Techniquement possible, mais presque certainement inutile dans le code réel. Donc, si vous écrivez un outil d'analyse statique, cela ne vous causera probablement aucun problème.

Pour être juste, chaque langue de la valeur de son sel a ce problème, ou quelque chose de similaire. À titre d'exemple, jetez votre walker de code préféré à ce code LISP: xxx

Vous ne pouvez probablement pas prédire qu'il s'agit d'une boucle qui produit une liste, car le iTER macro est opaque et nécessiterait des connaissances spéciales pour comprendre. La réalité est que cela est gênant de la théorie (je ne peux pas comprendre mon code sans l'exécuter, ou au moins exécuter le iTer macro, qui peut ne pas arrêter de courir avec cette entrée), mais très utile En pratique (l'itération est facile pour le programmeur d'écrire et du futur programmeur à lire).

Enfin, beaucoup de gens pensent que Perl manque d'analyse statique et de refactoring, comme Java a, à cause du relatif difficulté à l'analyser. Je doute que cela soit vrai, je pense juste que le besoin n'est pas là et personne n'a gêné de l'écrire. (Les gens ont besoin d'une "peluche", donc il y a Perl :: critique, par exemple.)

Toute analyse statique que j'ai besoin de faire de Perl pour générer du code (certaines macros EMACS pour maintenir des comptoirs de test et Makefile.pl) a bien fonctionné. Les cas d'angle weir pourrait-ils jeter mon code? Bien sûr, mais je ne sors pas de mon chemin pour écrire du code impossible à maintenir, même si je pouvais.


6 commentaires

Alors, pourquoi utilisez-vous les termes «Exécuter du code PERL au moment de la compilation» plutôt que de «compiler le code PERL au moment de l'exécution». Quelle est la distinction? C'est pourquoi j'ai demandé à propos de la terminologie.


Donc, sa juste la terminologie de la communauté Perl? Nous serions tout aussi corrects de dire que la deuxième "compile" se produit lors de l'exécution du bloc de début, afin de dire que la première exécution se produit pendant la phase de compilation du code principal?


Oui, bien que la fin de la phase de compilation initiale soit spéciale.


Ce n'est pas seulement une terminologie. Bien que Perl puisse exécuter un certain code dans la phase de compilation et compiler peut-être un certain code dans la phase d'exécution, chacun de ceux-ci a également des crochets à courir au début et à la fin des phases. Bien qu'ils soient un peu flous à l'intérieur, ils ont des frontières où d'autres choses se produisent.


@brian D FOY: Oui, mais les noms donnés à ces phases de la communauté PERL ne reflètent pas de manière unique quelles sont les phases, et les noms choisis pour ces phases auraient été aussi précis dans l'autre sens.


@Paul, non, les noms reflètent la grande tâche de chacune de ces phases. Les noms sont utiles, descriptifs et précis.



3
votes

C ++ a un problème similaire dans son système de modèle, mais cela n'arrête pas les compilateurs de la compiler. Ils vont simplement sortir ou courir pour toujours sur les cas d'angle où ce type d'argument s'appliquerait.


4 commentaires

Oui, bien-dit. Même idée que mon post, et beaucoup moins de mots :)


Ce n'est pas vraiment similaire - pour les modèles C ++, toutes les valeurs impliquées sont également des expressions temporelles et sont clairement distinctes des expressions d'exécution. Dans PERL, avec l'exemple donné à l'article lié, la fonction pourrait être définie différemment selon E.G. Une entrée d'utilisateur à chaîne, le reste du programme serait donc passé différemment à partir du moment de l'entrée. Il n'y a rien même à distance similaire à C ++.


@Pavel Vous pouvez créer (presque) l'analogue exact de l'exemple de l'article en C ++ à l'aide de modèles et de l'ambiguïté de la déclaration / d'initialisation. Le fait que Perl peut punter cela à l'exécution, alors qu'un compilateur C ++ doit le résoudre au moment de la compilation n'est pas pertinent.


@Segfault: L'analyse statique se produit avant l'exécution.



3
votes

Perl a une phase de compilation, mais elle est différente de la plupart des phases compilées normales en matière de code. Le Lexer de Perl transforme le code en jetons, puis un analyseur analyse des jetons pour former un arbre d'op. Cependant, commencez {} Les blocs peuvent interrompre ce processus et vous permettre d'exécuter du code. Lorsque vous effectuez un utiliser code>. Tous les commencent code> Les blocs exécutés avant toute autre chose, vous donnant un moyen de configurer des modules et des espaces de noms. Au cours de la "compile" globale d'un script, vous utiliserez probablement Perl pour déterminer comment le module PERL devrait ressembler quand c'est fait. Sub, nu, implique de l'ajouter au Glob pour le colis, mais vous n'avez pas besoin. Par exemple, il s'agit d'une manière (bien qu'édiable) de configurer des méthodes dans un module: xxx pré>

vous avez em> pour interpréter cela pour savoir même ce qu'il fait! Ce n'est pas très utile, mais ce n'est pas quelque chose que vous pouvez déterminer à l'avance. Mais c'est 100% de Perl valide. Même si cette caractéristique peut être maltraitée, elle peut également faire de grandes tâches, comme la construction de sous-marins compliqués que tous semblent très similaires, de manière programmatique. Cela rend également difficile de savoir, pour certains, ce que tout fait. P>

Cela ne veut pas dire qu'un script Perl ne peut pas être "compilé" - en Perl, la compilation est simplement déterminante, quelle raison alors, Le module devrait ressembler. Vous pouvez le faire avec un P>

perl -c myscript.pl
  • Comment un programme Perl 5 fonctionne a > li>
  • sur Perser Perl 5 li> ul> p>

  • 4 commentaires

    Vraisemblablement, vous pouvez faire vérifier le bloc de départ sur le système de fichiers ou le réseau, ce qui entraîne deux analyses d'un programme identique avec deux significations différentes?


    Absolument. J'ai vu (peut-être, mal guidé) Les développeurs PERL utilisent le bloc de départ pour analyser les arguments de la ligne de commande, puis modifier les variables disponibles à l'exécution basées sur cela. En fait, vous n'avez même pas besoin de le faire pendant la phase «Compiler»; Le code ci-dessus pourrait être exécuté plusieurs fois. Vous pouvez l'avoir dans une fonction, et même changer le comportement du module après avoir été "compilé". L'assurance maladie du code PERL est quelque chose qui n'est vraiment rivalisé que par d'autres langues dynamiques; Les langues de type LISP viennent à l'esprit comme un exemple d'excellence.


    Ok, mais ça vient de jouer avec la table des symboles. Mais une ligne ne peut pas changer de sens pendant le programme (au sens de l'article cité), pourrait-il?


    @Paul Biggar: L'article ne parle pas de l'analyse d'analyse pour un peu de code changeant pendant l'exécution, il parle de l'incapacité (dans le cas général) pour déterminer l'arborescence d'analyse de ce code sans rien exécuter.



    19
    votes

    Perl possède une phase de "heure de compilation" bien définie, suivie d'une phase "d'exécution" bien définie. Cependant, il existe des moyens de transition de l'un à l'autre. De nombreuses langues dynamiques ont des constructions eval qui permettent la compilation du nouveau code pendant la phase d'exécution; en Perl, l'inverse est aussi possible et commun. Commencez les blocs Blocs (et le bloc Implicit Begin Causé par Utilisez ) Invoque une phase d'exécution temporaire pendant compilation. Un bloc commence est exécuté dès qu'il est compilé, au lieu d'attendre le reste de l'unité de compilation (c'est-à-dire un fichier actuel ou actuel eval ) pour compiler. Étant donné que commencent S exécudi avant le code qui les suit est compilé, ils peuvent influencer la compilation du code suivant de manière pratiquement (bien que, dans la pratique, les principales choses qu'ils font sont d'importer ou de définir des sous-routines, ou activer la stress ou les avertissements).

    A Utilisez FOO; est essentiellement équivalent à commencer {besoin foo; foo-> importer (); } , avec besoin d'être (comme EVAL String ) L'une des façons d'invoquer la compilation du temps d'exécution, ce qui signifie que nous sommes maintenant dans la compilation du temps d'exécution dans le délai de compilation et Le tout est récursif.

    Quoi qu'il en soit, ce qu'il se résume à la suppression de l'analyse Perl, car la compilation d'un bit de code peut être influencée par l'exécution d'un code de code précédent (qui peut en théorie Do n'importe quoi ), nous avons nous-mêmes une situation de type d'arrêt-problème; Le seul moyen d'analyser correctement un fichier Perl donné en général est en l'exécutant.


    1 commentaires

    Plus souvent, la compilation d'un bit de code peut être influencée par la compilation d'une pièce de code précédente - notamment si un identifiant est le nom d'un package ou d'un sous-produit.



    5
    votes

    Les gens ont utilisé beaucoup de mots pour expliquer diverses phases, mais c'est vraiment une question simple. Lors de la compilation de la source Perl, l'introprète Perl peut finir par faire fonctionner le code qui modifie la manière dont le reste du code analyse. Analyse statique, qui ne fonctionne aucun code, cela manquera.

    Dans ce Perlmonks Post, Jeffrey parle de ses articles dans L'évaluation PERL qui se détaille beaucoup plus en détail, y compris un exemple de programme qui n'utilise pas la même manière chaque fois que vous l'exécutez.


    0 commentaires