L'émergence des langages de programmation
3 mars 2008
Introduction
Les trois types de
langage
Intentions et
conventions
I - Le langage machine
II - La gestation des
langages (1944-1954)
III -
Naissance du premier langage : Fortran (1957)
Conclusion
Qui aujourd’hui, parmi les programmeurs, sait qu’il fut une époque où seuls quelques praticiens concevaient l’utilité des langages de programmation ? Tout le monde, ou presque, pensait alors que pour programmer efficacement il fallait impérativement utiliser le langage machine.
Si en informatique l’intuition peine tant à se former c’est que l’architecture des programmes, des systèmes d’information, est invisible – ou plus précisément qu’elle ne peut apparaître qu’à travers l’étroite fenêtre de l’écran, après un examen soigneux et beaucoup de réflexion. L’expert se forge des convictions qu'il lui est difficile de partager avec ceux qui n’ont pas examiné les choses d’aussi près que lui, et qui ne partagent donc pas son expérience.
D’ailleurs on ne parle pas à un ordinateur, on ne discute pas avec lui, on ne négocie pas : on le commande. L’expression « langage de programmation » est donc un de ces faux amis qui orientent l’intuition vers de fausses pistes : elle désigne en fait le dispositif de commande de l’automate c’est-à-dire une liste de termes associés chacun à sa définition, couplée à une liste de règles selon lesquelles organiser ces termes.
On peut nommer « vocabulaire » la liste des termes, « syntaxe » la liste des règles : il n’en reste pas moins une différence entre ce dispositif de commande et les langages que nous autres êtres humains parlons. L’économie des langages naturels est en effet celle de la suggestion : le choix des termes et la construction des phrases élaborent le réseau de connotations qui nous permet d’éveiller dans l’esprit de l’interlocuteur, avec un minimum de paroles, l’image ou l’intention présentes dans le nôtre. L’automate est par contre insensible à la suggestion comme aux connotations : un programme informatique doit être parfaitement explicite.
Entre le langage naturel de la conversation, de la littérature, et le langage de programmation s’intercale le langage de la théorie (qu’elle soit mathématique, physique ou philosophique). En effet si les concepts, inférences et relations de causalité que comporte une théorie doivent être formellement explicites, on ne peut la comprendre véritablement que si l’on adhère à l’intention qui a orienté le théoricien – et pour communiquer une intention, il faut recourir à la suggestion.
* *
Celui qui ne sait pas distinguer ces trois types de langage trébuche sur des obstacles. Le « littéraire pur », exclusivement sensible aux connotations, peine à lire les textes théoriques : dans un livre d’économie où alternent passages littéraires et passages mathématiques. Il faut ainsi, comme le skieur qui entre dans une neige plus difficile, ralentir fortement la lecture quand on passe des uns aux autres. Le « littéraire » peinera plus encore à lire un programme informatique car celui-ci est écrit, quoiqu’en disent certains, non pour être lu par un être humain mais pour être exécuté par l’automate.
Aux différences entre langage naturel, langage théorique et langage de programmation répondent, dans notre action et notre vie, des étapes différentes : le langage naturel est celui de la vie quotidienne et de l’action immédiate ; le langage théorique est celui de la réflexion, des anticipations, de la modélisation et de l’action différée ; le langage de programmation enfin, de création récente, commande l’automate qui assistera notre action et nos processus de production. Ces trois langages sont nécessaires chacun dans sa sphère propre et en outre ils communiquent : il n’existe pas de théorie ni de programme qui ne réponde à une intention et celle-ci ne peut s’exprimer que dans le langage naturel. Bien des erreurs, bien des difficultés et des échecs s’expliquent par une confusion entre ces trois types de langage, alors qu’ils cohabitent dans chaque entreprise, chaque institution.
Ayant décrit leurs différences et suggéré leur complémentarité, nous utiliserons l’expression « langage de programmation » – elle appartient au lexique courant – mais nous saurons qu’il faut, pour éviter les malentendus, la traduire par « dispositif de commande de l’automate ». Nous dirons parfois même « langage » tout court pour alléger le texte.
Dans tout langage – qu’il soit naturel, théorique, ou qu’il s’agisse d’un langage de programmation – on distingue des caractéristiques logiques, que le raisonnement peut déduire à partir des intentions de ses auteurs, et d’autres qui sont de pures conventions. Les noms que l’on donne aux choses, aux êtres que le langage distingue sont conventionnels. Certaines règles syntaxiques le sont aussi : dans un programme la fin d’une instruction se note par un passage à la ligne (Fortran), un point virgule (C), la clôture d’une parenthèse (Lisp) etc.
Dans l’apprentissage de tout langage la mémorisation des conventions formelles accapare l’essentiel de l’effort pédagogique : acquisition du vocabulaire d’une langue naturelle, de la nomenclature d’une théorie, des règles d’un langage de programmation. La compréhension des caractéristiques logiques du langage, par contre, suppose de connaître les intentions des auteurs du langage ainsi que les obstacles et outils auxquels ils ont été confrontés, toutes choses que les pédagogues explicitent rarement.
Cependant les conventions, une fois choisies, se solidifient en quelque sorte pour obéir à une logique qui sans être celle du raisonnement n’en a pas moins ses règles, et que l’on peut qualifier d’étymologique. Une langue naturelle évolue, par exemple, selon les lois de la phonétique ; et tout nouveau langage de programmation reprend les conventions d’autres langages, plus anciens, auxquelles ses créateurs se sont habitués. L’étymologie de certaines notations de Java remonte, à travers C++, jusqu’au langage C ; XML descend de SGML à travers HTML.
Quels que soient l’âge et l’expérience, on sera toujours un apprenti en matière de langage : ce que l’on ignore est incomparablement plus vaste que ce que l’on connaît. Mais l’apprentissage est facilité si l’on est psychologiquement prêt à accepter des conventions inévitablement arbitraires, et si l’on est assez curieux pour partir à la recherche des textes qui indiquent les intentions des créateurs. On peut enfin, en s’intéressant à l’étymologie, trouver un ordre sinon une logique dans les conventions elles-mêmes.
Ici nous entreprenons de décrire l’émergence des langages de programmation. Nous nous appuierons pour cela sur le témoignage de leurs créateurs. Ils décrivent leurs intentions, les obstacles qu’ils ont dû surmonter ; nous découvrirons l’origine de termes qui, comme « compilateur », font aujourd’hui partie du langage courant.
* *
Les langages de programmation, dénommés aussi langages de haut niveau, ont été bâtis pour surmonter les difficultés que le langage de la machine (ou « langage machine ») oppose à l’être humain : il faut donc partir du langage machine pour faire ressortir ces difficultés et la nécessité de langages plus commodes.
Au cœur de l’ordinateur résident un processeur et une mémoire, autrement dénommée « mémoire vive » ou « Random Access Memory », RAM[1]. Tout le travail de l’automate se déroule entre le processeur et la mémoire, le programme commandant par ailleurs les échanges avec des périphériques (écran, clavier, disque dur etc.).
Avant tout travail le programme et les données sont chargés dans la mémoire sous la forme d’une suite de 0 et de 1 concrétisés par deux niveaux différents de tension électrique. Du programme, le processeur reçoit des instructions codées en binaire qu’il exécute l’une après l’autre. Il dispose de registres pour stocker et traiter une instruction, les adresses des données auxquelles elle s’applique et les données elles-mêmes.
Chaque instruction obéit à une structure simple : un code pour l’opération (additionner, soustraire, multiplier, diviser, changer de signe etc.), un code pour chacune des adresses qu’ont dans la mémoire les données concernées par l’opération, un code pour l’adresse où il faudra inscrire le résultat.
La vitesse d’un processeur se mesure en MIPS (millions d’instruction par seconde). Considérons une opération des plus simples, comme déplacer le curseur en fin de ligne lors de la saisie d'un texte. Si nous utilisons un raccourci clavier cette action prendra un quart de seconde et se traduira par environ 20 000 instructions élémentaires. Si le processeur a une vitesse de 500 MIPS, exécuter 20 000 instructions lui demande une toute petite fraction (4 % exactement) de microseconde.
Cet exemple illustre ce qui distingue la physique de l’automate, qui traite à toute vitesse des instructions écrites en binaire, de la physique de sa programmation et de celle de son utilisation. Se servir d’un raccourci clavier pour donner un ordre à l’ordinateur, c’est tout simple et un quart de seconde est pour un être humain un délai très court. Cela déclenche dans le processeur une avalanche d’instructions qu’il serait fastidieux de programmer : on conçoit le besoin de traduire automatiquement les ordres de l’utilisateur en instructions élémentaires. Les interpréteurs, les compilateurs et le système d’exploitation ont été progressivement conçus pour répondre à ce besoin.
Les tout premiers programmes étaient cependant codés en binaire et contenaient toutes les instructions élémentaires. Les écrire était pénible : l’être humain mémorise difficilement des codes en binaire et les programmes écrits de la sorte sont pratiquement illisibles.
Un premier progrès a consisté à organiser les bits en octets et à écrire les instructions en octal, un interpréteur traduisant ensuite les octets en bits pour produire le programme exécutable. Mais des codes numériques restent difficiles à mémoriser et à lire : les assembleurs ont permis de coder les instructions en caractères alphabétiques.
Bits, octal et assembleur
Voici une instruction telle qu’elle se présente au processeur[2] :
011011 000000 000000 000000 000001 000000
Transcrite en octal, elle prend la forme :
27 0 0 0 0 64
et enfin en assembleur :
CLA 0 0 0 0 64
Un programme en assembleur sera plus lisible pour un être humain, plus facile à vérifier et à corriger, que ne l’est le programme en octal ou, pis, le programme exécutable auquel il équivaut. Mais il code explicitement chacune des instructions élémentaires[3] : sa seule différence avec le code exécutable réside donc dans la façon dont l’instruction élémentaire est écrite. L’assembleur est identique, à une interprétation simple près, au langage de la machine : il ne mérite pas le nom de langage de programmation[4] .
Les premiers programmeurs, ceux des années 1940 que l’on nommait d’ailleurs « codeurs[5] », codaient en octal. Les langages de programmation n’ont émergé que très difficilement car leurs promoteurs ont dû surmonter des préjugés : l’opinion commune était alors que l’on ne pouvait coder qu’en octal.
Le premier langage de programmation digne de ce nom a été Fortran, publié en avril 1957. Cette réalisation étonnante a été préparée par une longue période de gestation lors de laquelle furent progressivement conçus les outils sur lesquels s’appuie un langage (interpréteurs, compilateurs, systèmes d’exploitation), et définies les exigences auxquelles il doit répondre.
II - La gestation des langages (1944-1954)
Nous disposons d’un témoignage précieux : l’exposé introductif de Grace Hopper[6], un des tout premiers « codeurs », à la conférence sur l’histoire des langages de programmation (HOPL) organisée par l’ACM en 1978[7]. Nous en reprenons ici certains éléments.
* *
Après son entrée dans la marine en 1943 Grace Hopper est chargée de produire des programmes pour le Mark I, précurseur des ordinateurs modernes. En 1949, elle programme le premier compilateur, A-0, qui aura pour successeurs A-1 et Math-Matic. En 1955, elle spécifie le langage Flow-Matic, contribution majeure au Cobol dont elle supervisera aussi le développement.
Grace Hopper dit avoir passé 20 ans à se battre contre l’« establishment ». Dans les premières années de l’informatique, tout le monde pensait que l’on ne pouvait programmer un ordinateur qu’en octal. Puis quelques rares personnes ont admis que l’on puisse programmer en assembleur…
Le Mark I disposait de programmes câblés dans la machine pour calculer des sinus, exponentielles etc. mais ces programmes étaient trop généraux. Les codeurs avaient besoin de méthodes finement adaptées à chacun des problèmes qu’ils traitaient. Ils avaient commencé à programmer des fonctions (subroutines). Si un codeur devait calculer le sinus d’un angle inférieur à 45° il appelait un collègue, lui demandait sa fonction sinus puis la copiait dans son cahier. Les codeurs ont fini par voir qu’il fallait disposer d’un format général pour copier les fonctions, et Grace Hopper l’a écrit pour le Mark I. Ainsi dès 1944 les codeurs ont disposé d’un premier outil pour programmer mieux et plus vite.
La communication était rare alors entre les informaticiens, sinon par le canal de relations personnelles. Pendant quelques années, chacun a dû pratiquement tout inventer pour lui-même. La toute première réunion sur la programmation s’est tenue à Harvard en 1948. En 1951 la Navy inaugura une série de trois séminaires sur le codage, la programmation automatique etc. (le mot software n’existait pas encore). Quelques articles ont effleuré la question de la programmation mais il n’existait pas de réelle assistance pour écrire des programmes.
Les Britanniques Wheeler, Wilkes et Gill ont cependant publié un livre montrant qu’ils avaient conçu, avant même de construire l’ordinateur, une bibliothèque de fonctions aux interfaces d’entrée-sortie standardisées. Une telle bibliothèque permettait de programmer un peu plus vite.
* *
En 1949 le Short Order Code de John Mauchly a permis au Binac de travailler en décimal et en virgule flottante. Short Code utilisait des mots de deux caractères numériques : un mot représentait « X », un autre le signe « égale », un autre « a », un autre « + », un autre « b ». Les fonctions étaient stockées dans la mémoire et le code contenait des références symboliques aux fonctions. C’était un langage interprété : le programme lisait chaque instruction, sautait jusqu’aux fonctions qu’elle appelait, les exécutait, puis allait à l’instruction suivante. Il ne fournissait pas un véritable code objet. Nous dirions aujourd’hui que c’était une machine virtuelle, et pour les codeurs c’était un pseudo code implémenté à travers un programme.
Le Short Code a fait comprendre à Grace Hopper qu’il était possible de programmer autrement qu’en langage machine. Le Sort-Merge Generator de Betty Holberton la convainquit que l’on pouvait utiliser l’ordinateur pour écrire des programmes : on introduisait les spécifications des fichiers et le Sort-Merge Generator produisait un programme de tri et de classement ainsi que la gestion des entrées-sorties sur les lecteurs de bande. Il contenait une première version de mémoire virtuelle car il gérait les pages automatiquement.
* *
L’« establishment » estimait cependant qu’un ordinateur, n’ayant ni l’imagination ni l’habileté d’un être humain et ne sachant faire que de l’arithmétique, serait à tout jamais incapable d’écrire un programme. Grace Hopper soutint par contre dès 1952 que l’on pouvait programmer tout ce qu’il était possible de définir complètement, et que l’on pourrait ainsi incorporer l’habileté humaine dans un générateur.
A l’automne 1951 on lui demanda de construire pour l’Univac I une bibliothèque de fonctions suffisamment standardisée pour que tout le monde puisse s’en servir. Les programmeurs utilisaient alors des fonctions, les copiaient d’un programme à l’autre, mais elles démarraient toutes à la ligne 0 puis continuaient séquentiellement : quand on les copiait dans un autre programme il fallait additionner toutes ces adresses. En outre les programmeurs faisaient des erreurs quand ils copiaient un programme : un 4 se transformait parfois en un delta, un B en 13 etc. Mieux valait faire copier les fonctions par l’ordinateur : c'est ainsi que naquit le A-0 que Grace Hopper programma entre octobre 1951 et mai 1952. Il a été nommé « compilateur » parce qu’à chaque fonction était associé une appellation et que les fonctions étaient dans une bibliothèque : or quand on extrait des documents d’une bibliothèque on dit qu’on les « compile ».
L’A-0 n’était ni un langage, ni ce que l’on appellerait aujourd’hui un compilateur, mais une série d’appels de fonctions associées chacune à ses arguments. Il ne comportait aucune optimisation : il s’agissait d’écrire rapidement des programmes de calcul qui ne seraient utilisés qu’une fois, et d’obtenir rapidement un résultat. Grace Hopper l’a soigneusement documenté parce que personne ne croyait qu’il puisse fonctionner[8]. Son argument était le suivant : on utilisait des fonctions dûment vérifiées et on les assemblait avec un programme automatique lui aussi vérifié ; les seules erreurs que le programmeur puisse faire étaient donc des erreurs de logique.
Le Mark I pouvait faire trois additions par seconde avec des nombres de 23 chiffres. C’était alors la machine la plus fantastique qui ait jamais été construite ! Mais l’Univac I faisait 3 000 additions par seconde. Il avalait les programmes à toute vitesse, alors que les programmeurs n’avaient pas accéléré au même point : il fallait donc trouver le moyen de programmer plus vite. Par ailleurs de plus en plus de gens voulaient résoudre des problèmes mais répugnaient à coder en octal et à manipuler des bits.
Le but des premiers informaticiens n’était pas de concevoir un langage de programmation. Ils étaient indifférents aux virgules et points-virgules mais voulaient écrire plus vite des programmes corrects et répondre plus vite aux besoins – y compris à ceux des ingénieurs, des commerciaux et pas seulement à ceux des programmeurs. Il leur fallait aussi s’adapter à diverses formes d’intuition : certains préfèrent les notations symboliques, d’autres les notations proches du langage naturel. Il ne convenait pas de contraindre tout le monde à se plier au formalisme mathématique.
En novembre 1952 apparut l’Editing Generator de Millie Coss. Le traitement de texte était pour les programmeurs un problème délicat : pour introduire des mots, des points, des « $ », pour supprimer des zéros, il leur fallait tout faire à la main. Comme ils savaient quel format ils voulaient donner à leurs programmes, il leur était utile de disposer d’un générateur de texte. Editing Generator prenait le format du fichier, le format des enregistrements, le format du document de sortie, puis produisait le code pour passer de l’un à l’autre.
Cependant l’écriture des spécifications en A-0 était lourde. Chaque instruction était un mot de douze caractères alpha-décimaux comportant trois adresses : les trois premiers caractères désignaient une opération, les trois suivants une donnée, puis venaient trois autres pour une autre donnée et enfin les trois derniers pour le résultat. Les programmeurs s’y étaient tellement habitués qu’ils croyaient que le monde entier raisonnait ainsi. En superposant ce codage à l’A-0 à l’aide d’un traducteur et en ajoutant des fonctions pour traiter les entrées-sorties Grace Hopper a obtenu le compilateur A-2.
Ce langage a permis de programmer le calcul différentiel. Tout le monde disait que c’était impossible parce que « les ordinateurs ne sont pas capables de faire autre chose que de l’arithmétique ». Il a fallu « vendre » l’A-2 non seulement aux utilisateurs mais aussi aux managers, et convaincre ces derniers qu’il était rentable de mettre au point des fonctions qui aideraient à programmer. A la fin de 1953 les utilisateurs étaient satisfaits de l’aide que l’A-2 leur apportait, mais il restait « évident » dans la profession qu’il était plus efficace de programmer en octal.
En 1954 furent enfin publiées les spécifications de Fortran, premier vrai langage de programmation. On n’aurait pas pu concevoir Fortran si l’on n’avait pas conçu auparavant le générateur, le compilateur et les autres outils pour réaliser des langages.
* *
Les méthodes qui conviennent pour construire un langage de type mathématique ne conviennent pas pour produire un langage de traitement des données.
Si en mathématiques tout le monde sait ce qu’est un sinus, il n’existait pas de vocabulaire commun pour le traitement des données. L’équipe de Grace Hopper a analysé 500 programmes de traitement de données et identifié 30 verbes qui lui semblaient être les opérateurs du traitement de données.
On peut écrire les programmes mathématiques dans un langage mathématique, mais il faut écrire les programmes de traitement des données dans une langue naturelle. L’establishment déclara que c’était impossible parce que les ordinateurs ne pourraient pas comprendre l’anglais ; Grace Hopper répondit qu’elle n’avait jamais pensé qu’ils le puissent, qu’il s’agissait simplement de comparer des suites de bits.
Elle publia en janvier 1955 un projet de compilateur pour le traitement des données. Le langage – un pseudo code – était composé de mots anglais de longueur variable séparés par des espaces et de phrases terminées par des points. Pour pouvoir convaincre, elle décida de construire un prototype. Il fallait gérer des listes d’opérations, de fonctions, de sauts, de stockage. Les managers ne comprenaient pas ce qu’est une liste : elles furent baptisées « fichiers » et l’obstacle fut levé.
Le prototype ne pouvait contenir que 20 instructions et cela paraissait peu pour demander un gros budget. Alors les programmeurs ont remplacé les mots anglais par des mots français, puis allemands. Les managers ont été impressionnés ! Il était évident pour eux qu’un ordinateur américain ne pourrait jamais « comprendre » le français, ni l’allemand, pourtant il le faisait. En fait, ce « langage » n’était pas un vrai langage mais seulement un code. Ce qui était pour les programmeurs une simple substitution de bits avait cependant fait faire à l’ordinateur une chose que les managers avaient jugée impossible : pénétrer le territoire des langues étrangères. Des choses très simples pour le programmeur semblent aux managers venir d’un autre monde.
Ce compilateur fut nommé Flow-Matic. Comme la mémoire ne comportait que 1 000 mots il fallait deux heures pour compiler un programme tandis que les lecteurs de bande tournaient à toute allure.
Un langage n’est pas très utile s’il fournit des résultats différents selon la machine : à la fin des années 60 la Navy souhaitait que tous les compilateurs Cobol fournissent le même résultat, quelle que soit la machine utilisée. Grace Hopper fut chargée de concevoir des programmes pour valider un compilateur Cobol en contrôlant son fonctionnement et en comparant ses résultats aux résultats standards. Pour la première fois, on utilisait ainsi un programme pour vérifier un autre programme.
III - Naissance du premier langage : Fortran (1957)
Les origines de Fortran ont été décrites par John Backus[9], son créateur. De façon significative, il accorde plus d’importance à la conception du compilateur qu’à celle du langage lui-même.
* *
Avant 1954 presque tous les programmes étaient écrits en langage machine ou en assembleur. La programmation était considérée comme un art complexe, créatif, et on croyait l’imagination humaine indispensable pour écrire des programmes efficaces. L’essentiel des difficultés provenait des limitations des ordinateurs de l’époque : ils n’avaient pas de registres d’index, les opérations en virgule flottante n’étaient pas câblées dans la machine, les jeux d’instructions étaient limités (ils avaient par exemple un AND mais pas un OR), les entrées-sorties étaient primitives. La programmation automatique (automatic programming) visait à surmonter ces obstacles à l’aide d’adresses symboliques et de nombres décimaux.
La plupart des systèmes de programmation automatique, comme par exemple le compilateur A-2, fournissaient un ordinateur synthétique avec un code d’opérations différent de celui du langage machine, le calcul en virgule flottante, des registres d’index et des commandes d’entrée-sortie. Mais les instructions de l’A-2, au lieu de s’écrire dans un pseudo code commode, étaient des séquences compliquées d’« instructions de compilation » sous diverses formes, du code machine lui-même jusqu’à de longs groupes de mots ou des instructions abrégées qui devaient être traduites en instructions de compilation.
Le langage algébrique de Laning et Zierler était simple et élégant. Il identifiait les variables avec un caractère et un indice, et les fonctions par la lettre « F » suivie d’un exposant numérique indiquant son numéro. Quand on utilisait ce langage le temps d’exécution était multiplié par dix.
Pour la plupart des programmeurs « automatic programming » signifiait simplement de fournir des codes pour les opérations et des adresses symboliques ; pour d’autres il s’agissait de puiser des fonctions dans une bibliothèque et d’insérer dans chacune d’entre elles les adresses des opérandes.
Ces systèmes de programmation automatique divisaient la vitesse de la machine par un facteur cinq à dix. L’essentiel du temps était accaparé par le traitement en virgule flottante. Simuler l’indexation et d’autres opérations de type « administratif » pouvait se faire en utilisant des fonctions peu efficaces car quoique très lentes elles demandaient beaucoup moins de temps que le travail en virgule flottante.
Les limitations de ces systèmes avaient convaincu les programmeurs qu’il était impossible d’automatiser efficacement la programmation. En outre certains gourous avaient prétendu offrir des systèmes capables de comprendre le langage humain ainsi que les besoins des utilisateurs mais ces systèmes s’étaient révélés à l’usage incommodes et inefficaces, limités qu’ils étaient à quelques tâches administratives et en outre remplis d’exceptions.
Dans un centre informatique, le coût de la programmation était du même ordre que le loyer de l’ordinateur. De surcroît le quart ou la moitié du temps d’ordinateur était accaparé par le déboguage. Ainsi la programmation et le déboguage représentaient les trois quarts du coût de l’informatique et cela allait empirer si le prix des ordinateurs diminuait. C’est pourquoi John Backus a proposé à IBM à la fin de 1953 de lancer le projet Fortran.
* *
L’arrivée de l’IBM 704, avec les virgules flottantes et les index en dur, changea entièrement la situation. Il supprimait la raison d’être des anciens systèmes et, en accélérant les calculs en virgule flottante, ne laissait plus aucune place où cacher les inefficacités.
Compte tenu du scepticisme dominant envers la programmation automatique et de l’impossibilité de cacher désormais les inefficacités, Backus était sûr que le système auquel il pensait ne pourrait être accepté que s’il était prouvé qu’il fournissait des programmes au moins aussi efficaces que ceux qui avaient été programmés à la main. Le plus grand défi lui semblait ainsi résider non dans la conception du langage mais dans la programmation du compilateur (ou, comme on disait alors, du traducteur).
Bien sûr l’un de ses buts était de concevoir un langage qui permettrait à des ingénieurs et des scientifiques de programmer eux-mêmes pour le 704. Il voulait aussi éliminer les tâches administratives, la planification répétitive et détaillée qu’implique un codage à la main. Il fallait permettre les affectations (assignment statements), les variables indexées et l’instruction DO.
Ignorant tout des difficultés de la conception des langages qui sont apparues plus tard (structure de blocs, expressions conditionnelles, déclarations de type), il estimait avoir défini une bonne base pour le langage : tout ce qui a émergé d’autre par la suite est apparu progressivement. Il espérait aussi que Fortran appliquerait automatiquement des techniques laborieuses mais efficace de codage qu’un programmeur humain n’aurait ni le temps, ni le l’envie d’utiliser[10].
A la charnière de 1954 et de 1955 l’équipe qui préparait Fortran a tenu des conférences avec les utilisateurs pour les informer du projet et s’enquérir de leurs objections et besoins. Ces conférences n’ont pas servi à grand-chose : les utilisateurs avaient entendu trop de descriptions enthousiastes de systèmes qui les avaient déçus par la suite et ils ne prenaient pas ce projet au sérieux. En particulier, ils ne croyaient pas qu’il soit possible de produire automatiquement un programme efficace.
* *
Le travail sur le compilateur a commencé au début de 1955. L’équipe avait d'abord défini le code en langage machine traduisant diverses expressions en langage source.
Le travail fut organisé d’abord en trois sections auxquelles il fallut par la suite en ajouter trois autres. Chaque section était réalisée par un groupe de deux ou trois personnes qui développait ses programmes et s’assurait de leur compatibilité avec ceux des sections voisines.
La section 1 devait lire la totalité du code source, compiler ce qu’elle pouvait (opérations arithmétiques, entrées-sorties) et classer le reste dans des tables appropriées. Les opérations arithmétiques furent ainsi optimisées et les entrées-sorties furent codées sous la forme d’une série d’instructions DO.
La section 2 devait analyser la structure du programme afin de produire un code optimisé à partir des instructions DO et des références aux données indexées, ce qui impliquait de traiter une grande diversité de cas particuliers. Cette section a fourni un code dont l’efficacité a surpris les programmeurs qui l’examinaient.
Le 704 n’ayant que trois registres d’index, il apparut rapidement qu’il ne serait pas facile de le programmer de façon optimale. Backus a donc décidé de faire comme si l’ordinateur disposait d’un nombre infini de registres d’index et de remettre à plus tard la réduction de ce nombre à trois. Cela l’a conduit à créer deux sections nouvelles, 4 et 5 (la section 3 fut ajoutée pour donner au produit des sections 1 et 2 la forme requise par les sections 4 et 5).
La section 4 devait diviser le programme produit par les sections 1 et 2 en blocs ne contenant aucun branchement, puis faire par simulation une analyse statistique de la fréquence d’exécution de chaque bloc et rassembler l’information sur l’utilisation des registres d’index.
La section 5 devait transformer le programme en ramenant à trois le nombre des registres d’index. Avec la section 2 c’était la section la plus compliquée et elle a eu une grande influence sur la conception des compilateurs ultérieurs.
Enfin la section 6 assemblait le résultat sous forme binaire et y introduisait le code des fonctions puisées dans la bibliothèque.
La compilation introduisait dans le programme des changements qui le rendaient plus efficace mais auxquels on n’aurait jamais pensé. La transformation était si radicale que les programmeurs croyaient parfois que le compilateur avait fait une erreur – mais après une étude approfondie ils constataient qu’il était correct. Parfois le programme était complètement réorganisé pour économiser une instruction. Dans certains contextes une même instruction DO pouvait ne produire aucune instruction, alors que dans d’autres contextes elle produisait un grand nombre d’instructions à divers endroits du programme.
Après avoir publié Fortran en avril 1957 l’équipe s’est occupée de son déboguage jusqu’à la fin de l’été. Un flot de lettres, télégrammes et appels téléphoniques venant des utilisateurs lui apportait des problèmes. En avril 1956, plus de la moitié des centres informatiques équipés de 704 utilisaient Fortran pour réaliser plus de la moitié de leurs travaux.
En automne 1957 l’équipe a commencé le travail pour traiter des problèmes qu’elle avait laissés d’abord de côté et corriger certaines lacunes : il fallait introduire de meilleurs outils de diagnostic, des commentaires plus clairs, et permettre à l'utilisateur de définir de nouvelles fonctions. Cela conduira à Fortran II au printemps de 1958. Cependant la durée de la compilation restait excessive et le déboguage prenait beaucoup de temps : c’était le principal défaut de Fortran II, et les versions ultérieures du langage ont tenté de le corriger.
Après 1957, de nombreux autres langages ont été conçus, répondant à des finalités diverses. Les langages se sont diversifiés, certains comme Lisp semblant appartenir à un tout autre monde que Fortran. En 1967 Sammet en a dénombré 120 dont 20 étaient morts ou obsolètes, 35 étaient peu utilisés, 50 étaient spécialisés dans un domaine d’application, 15 enfin étaient largement utilisés[11]. Aujourd’hui, la descendance de Fortran dessine une arborescence d’une grande complexité ; à coup sûr il est plus difficile de suivre la filiation étymologique de ces divers langages que de saisir l'arbre par la racine et décrire son émergence.
[1] Dans « Random Acess Memory » le mot « random » ne signifie pas que l’accès à une donnée en mémoire se fasse au hasard, mais que le délai nécessaire à l’accès ne dépend pas de l’adresse de la donnée.
[2] Sammet, op. cit. p. 2.
[3] Il existe toutefois en assembleur des « macros », qui sont autant de raccourcis pour les suites d’instructions les plus fréquentes.
[4] Jean E. Sammet, Programing Languages : History and Fundamentals, Prentice Hall 1969, p. 1.
[5] « Nous n’étions pas des programmeurs à cette époque-là. Ce mot n’était pas encore venu d’Angleterre. Nous étions des codeurs » (Grace Hopper).
[6] Grace Hopper, « Keynote Address of the Opening Session », in Richard L. Wexelblat, History of Programming Languages, Academic Press, 1981, p. 7 ; cf. http://en.wikipedia.org/wiki/Grace_hopper.
[7] L’ACM a organisé trois conférences sur l’histoire des langages de programmation : en 1978, 1993 et 2007 : cf. http://research.ihost.com/hopl/HOPL-III.html et http://en.wikipedia.org/wiki/HOPL.
[8] « I knew damn well nobody was ever going to believe it was going to work ! »
[9] John Backus, « The History of Fortran I, II and III », in Wexelblat, op. cit. p. 25.
[10] « Fortran may apply complex, lenghty techniques in coding a problem which a human coder would have neither the time, nor the inclination to derive or apply » (Preliminary Report, 1954).
[11] Sammet, op. cit. p. vi.
Pour lire un peu plus :
-
Langage et "langage"
- Évolution du logiciel
- La programmation comme hobby
- La qualité des programmes informatiques
http://www.volle.com/adresse.htm
© Michel VOLLE, 2008
GNU
Free Documentation License