J'ai entendu tout à l'heure qu'il y avait un compilateur qui tentait de corriger les erreurs de syntaxe en analysant le contexte et en déduisant ce qui était prévu.
Un tel compilateur existe-t-il vraiment? Évidemment, il a peu de valeur pratique, mais il serait très intéressant de jouer avec et d'apprendre.
Réponses:
Dans un certain sens, l'acte de compilation est infère ce que certains syntaxe est censé faire, et donc une erreur de syntaxe est lorsque le compilateur ne parvient pas à comprendre. Vous pouvez ajouter plus de "devinettes" pour que le compilateur infère d'autres choses et soit plus flexible avec la syntaxe, mais il doit le faire en déduisant par un ensemble spécifique de règles. Et ces règles deviennent alors une partie du langage, et ne sont plus des erreurs.
Donc, non, il n'y a pas vraiment de tels compilateurs, car la question n'a pas de sens. Deviner quelles erreurs de syntaxe sont censées faire selon un ensemble de règles devient simplement une partie de la syntaxe.
En ce sens, il existe un bon exemple de compilateur qui fait ceci: n'importe quel compilateur C. Souvent, ils imprimeront simplement un avertissement de quelque chose qui ne devrait pas être, puis supposeront que vous vouliez dire X, et continuer. Il s'agit en fait de «deviner» du code peu clair (bien que ce ne soit pas la syntaxe en soi), quelque chose qui aurait tout aussi bien pu arrêter la compilation avec une erreur, et donc être considéré comme une erreur.
la source
Cela semble vraiment dangereux. Si un compilateur tente de déduire votre intention, la déduit incorrectement, corrige le code, puis ne vous le dit pas (ou vous indique dans un avertissement que vous, comme tout le monde, l'ignorez), alors vous êtes sur le point d'exécuter du code qui peut faire sérieusement des dégâts.
Un compilateur comme celui-ci est probablement quelque chose qui n'a PAS été créé intentionnellement.
la source
L'IDE pour un langage de programmation a généralement de nos jours un compilateur qui s'exécute en arrière-plan, de sorte qu'il peut fournir des services d'analyse comme la coloration de la syntaxe, IntelliSense, les erreurs, etc. De toute évidence, un tel compilateur doit être capable de donner un sens à du code profondément cassé; la plupart du temps lors de l'édition, le code n'est pas correct. Mais nous devons encore lui donner un sens.
Cependant, la fonction de récupération d'erreur n'est généralement utilisée que lors de l'édition; cela n'a pas beaucoup de sens de permettre cela pour une compilation réelle dans des scénarios "principaux".
Fait intéressant, nous avons intégré cette fonctionnalité dans le compilateur JScript.NET; Fondamentalement, il est possible de mettre le compilateur dans un mode où nous permettons au compilateur de continuer même si une erreur est rencontrée, si l'EDI en aurait récupéré. Vous pouvez taper du code Visual Basic , exécuter le compilateur JScript.NET dessus et avoir une chance raisonnable qu'un programme de travail sorte à l'autre bout!
Il s'agit d'une démonstration amusante, mais elle s'avère ne pas être une très bonne fonctionnalité pour les scénarios "principaux" pour de nombreuses raisons. Une explication complète serait assez longue; la brève explication est que cela rend les programmes qui fonctionnent de manière imprévisible et accidentelle , et il est difficile d'exécuter le même code via plusieurs compilateurs ou plusieurs versions du même compilateur. Les dépenses importantes que la fonctionnalité ajoute ne sont pas justifiées par les petits avantages.
Peter Torr, qui a proposé la fonctionnalité dans la journée, en parle brièvement dans ce blog de 2003 .
Bien que nous exposions cette fonctionnalité via les API d'hébergement de scripts du moteur JScript .NET, je ne connais aucun vrai client qui l'ait jamais utilisée.
la source
La première chose qui me vient à l'esprit est l' insertion automatique des points-virgules de Javascript . Une caractéristique horrible et horrible qui n'aurait jamais dû faire son chemin dans la langue.
Cela ne veut pas dire qu'il n'aurait pas pu faire mieux. S'il regardait la ligne suivante, il pourrait peut-être mieux deviner l'intention du programmeur, mais à la fin de la journée, s'il y a plusieurs façons valides que la syntaxe aurait pu disparaître, alors il n'y a vraiment pas de substitut pour le programmeur étant explicite.
la source
Il me semble que si un compilateur peut corriger une syntaxe incorrecte, cette syntaxe doit être documentée dans le langage.
La raison des erreurs de syntaxe est qu'un analyseur n'a pas pu créer l'arbre de syntaxe abstrait à partir du programme. Cela se produit lorsqu'un jeton n'est pas à sa place. Afin de deviner où ce jeton doit être, s'il doit être supprimé ou si un autre jeton doit être ajouté pour corriger l'erreur, vous aurez besoin d'une sorte d'ordinateur qui peut deviner l'intention d'un programmeur. Comment une machine pourrait-elle deviner que:
Devait être:
Il pourrait tout aussi bien être un des éléments suivants:
56
,5 - 6
,5 & 6
. Il n'y a aucun moyen pour un compilateur de savoir.Cette technologie n'existe pas encore.
la source
Bien que ce ne soit pas tout à fait la même chose, c'est en quelque sorte la raison pour laquelle le HTML est devenu la catastrophe. Les navigateurs ont toléré un mauvais balisage et la prochaine chose que vous saviez, le navigateur A ne pouvait pas être rendu de la même manière que le navigateur B (oui, il y a d'autres raisons, mais c'était l'une des rares, en particulier il y a environ 10 ans avant que certaines règles de relâchement ne deviennent conventionnelles. ).
Comme le déduit Eric Lippert, beaucoup de ces choses sont mieux gérées par l'IDE, pas par le compilateur. Cela vous permet de voir ce que les bits automatiques tentent de visser pour vous.
La stratégie que je pense qui prédomine maintenant est le raffinement continu du langage au lieu de relâcher le compilateur: si c'est vraiment quelque chose que le compilateur peut comprendre automatiquement, alors introduisez une construction de langage bien définie autour de lui.
L'exemple immédiat qui me vient à l'esprit est les propriétés automatiques en C # (pas le seul langage qui a quelque chose de similaire): étant donné que la majorité des getters / setters dans n'importe quelle application ne sont en fait que des wrappers autour d'un champ, permettez simplement au développeur d'indiquer leur intention et laissez le compilateur injecter le reste.
Ce qui me fait alors réfléchir: la plupart des langages de style C le font déjà dans une certaine mesure. Pour les choses qui peuvent être déterminées automatiquement, affinez simplement la syntaxe:
Peut être réduit à:
En fin de compte, je pense que cela se résume à ceci: La tendance est que vous ne rendez pas le compilateur "plus intelligent" ou "plus lâche". C'est le langage qui est rendu plus intelligent ou plus lâche.
De plus, trop «d'aide» peut être dangereux, comme le bug classique «if»:
la source
if (x && y) dothis(); else dothat();
aurait l'air un peu mieux.true
oufalse
.Lorsque je codais FORTRAN et PL / I à la fin des années 80 et au début des années 90 sur les systèmes de mini-ordinateur et d'ordinateur central DEC et IBM, je me souviens que les compilateurs se déconnectaient régulièrement des messages comme "erreur bla bla; en supposant bla bla et continuant .. . ". À l'époque, c'était un héritage des jours (encore plus tôt, avant mon époque) de traitement par lots et de cartes perforées où il y avait probablement une énorme attente entre la soumission de votre code à exécuter et l'obtention des résultats. Il était donc très logique pour les compilateurs de tenter de deviner le programmeur et de continuer plutôt que d'annuler la première erreur rencontrée. Attention, je ne me souviens pas que les "corrections" aient été particulièrement sophistiquées. Lorsque je suis finalement passé aux postes de travail interactifs Unix (Sun, SGI, etc.),
la source
Le but d'un compilateur est de produire des exécutables qui se comportent comme souhaité. Si un programmeur écrit quelque chose qui n'est pas valide, même si le compilateur peut deviner à 90% ce qui était prévu, il serait généralement préférable d'exiger du programmeur qu'il corrige le programme pour que l'intention soit claire, plutôt que de demander au compilateur d'aller de l'avant et de produire un exécutable. ce qui aurait une chance importante de cacher un bug.
Bien sûr, les langues devraient généralement être conçues de manière à ce que le code qui exprime clairement l'intention soit légal, et le code qui n'exprime pas clairement l'intention devrait être interdit, mais cela ne signifie pas qu'elles le sont. Considérez le code suivant [Java ou C #]
Avoir un compilateur ajouter un transtypage implicite pour l'affectation
f1
serait utile, car il n'y a qu'une seule chose logique que le programmeur pourrait vouloirf1
contenir (lafloat
valeur la plus proche de 1/10). Plutôt que d'encourager les compilateurs à accepter des programmes inappropriés, il serait préférable que la spécification autorise des conversions implicites de double à flottant dans certains contextes. D'un autre côté, l'affectation àd1
mai ou peut ne pas être ce que le programmeur avait vraiment l'intention, mais aucune règle de langage ne l'interdit.Les pires sortes de règles de langage sont celles où les compilateurs feront des inférences dans les cas où quelque chose ne pourrait pas légitimement compiler autrement, mais où un programme pourrait "accidentellement" être valide dans le cas où l'inférence était intentionnelle. De nombreuses situations impliquant une fin de déclaration implicite entrent dans cette catégorie. Si un programmeur qui a l'intention d'écrire deux instructions distinctes omet un terminateur d'instruction, un compilateur peut généralement réussir à déduire la frontière de l'instruction, mais peut parfois considérer comme une instruction quelque chose qui était censé être traité comme deux.
la source
Les erreurs de syntaxe sont particulièrement difficiles à corriger. Prenons le cas d'un droit manquant
)
: nous savons que nous pouvons réparer le code en en insérant un, mais il existe généralement de nombreux endroits où nous pourrions en insérer un et obtenir un programme syntaxiquement correct.Les identificateurs mal orthographiés sont beaucoup plus faciles (mais notez qu'il ne s'agit pas d'erreurs de syntaxe). On peut calculer la distance d'édition entre l'identifiant insoluble et tous les identifiants dans la portée, et en remplaçant le mot insoluble par celui que l'utilisateur voulait probablement dire, on trouverait un programme correct dans de nombreux cas. Cependant, il s'avère qu'il est toujours préférable de signaler l'erreur et de laisser l'IDE suggérer des remplacements valides.
la source
Un tel compilateur serait simplement une implémentation détendue et non standard du langage qu'il compile.
la source
Il a été essayé plusieurs fois, mais souvent, il n'a pas obtenu l'effet souhaité: pensez à HAL 9000 ou GlaDOS.
la source
En C, vous ne pouvez pas passer de tableaux par valeur, mais le compilateur vous permet d'écrire:
qui est ensuite réécrit en silence:
C'est stupide? Je préférerais une erreur grave ici au lieu d'une réécriture silencieuse, car cette règle spéciale a conduit de nombreux programmeurs à croire que les tableaux et les pointeurs sont essentiellement la même chose. Ils ne sont pas.
la source