ALGOL 68, la base de tous les langages modernes
Le but de cette fiche et de donner un idée d'ensemble de la syntaxe d'ALGOL 68, et montrer comment le langage à influencé ses successeurs, dont C, Pascal et tous les C-Like, notamment Go. Pour une connaissance détaillée du langage on se réfèrera aux manuels donnés en référence en bas de page.
Le premier compilateur ALGOL 68 a été réalisé en 1970 par Peck, Koster, Mailloux et Wijngaarden au IFIP Working Group. De leur coté, Nicklaus Wirth et Tony Hoare avaient déjà développé en 1966 ALGOL W, un autre successeur à ALGOL 60.
ALGOL W à été la base du langage Pascal, apparu aussi en 1970 et qui a en fait pris la place de langage universel que voulaient conférer les auteurs à ALGOL 68. Mais ce dernier a inspiré tous les C-Like.
Description du langage ALGOL 68
La complexité d'ALGOL 68 le rendrait en fait difficilement compréhensible à un programmeur moderne, ce que l'on ne voit pas dans le code ci-dessous qui se limite à la syntaxe la plus simple.
Les types
- int: Nombre entier.
- bool.
- real: Nombre réel.
- compl: Nombre complexe.
- char.
- string: Chaîne de caractères.
- bytes: Paire de caractères.
- struct.
- void.
- bits: Chaîne de bits.
- file: Fichier.
On notera que très logiquement, un nombre réel est représenté par le type real, repris par Pascal, alors que C utilise float qui est le nom de la représentation en mémoire: "floating point" ou "virgule flottante". Et C a été suivi bêtement par la plupart des languages ultérieurs.
Le type string est aussi remplacé dans C par char *, mais il reviendra ensuite dans C++ et dans les languages modernes.
Pour les types numériques, les modifieurs long et short précisent le nombre d'octets de représentation mémoire, ce qui est repris par C.
Les valeurs prédéfinies:
- nil: Rien, raccourci de "nihil" (rien) ou acronyme de "Not In List" du langage Lisp.
- true, false.
Les opérateurs
On les retrouve pour la plupart dans C.
- ( )
- , Séparateur.
- ; Terminateur.
- : Terminateur.
- =, := Assignement.
- [ ] Tranche, index ou déclaration de tableau.
- +, -, *, /, ^, %, %*: Arithmétiques.
- + est aussi opérateur de concaténation de chaînes.
- * peut aussi démultiplier un caractère ou une chaîne.
- >, >=, <, <=,
- =, eq: Egal.
- ~=, /=, ne: Non égal.
- +=, *=, /=: Assignement simplifié.
- #, co, comment: Commentaire, se termine par le même symbole.
- &, and, or: Opérateurs logiques.
L'opérateur non égal est le plus controversé. ALGOL 68 a plusieurs options, Pascal utilise <>, C utilise plutôt != ce qui est repris par tous les C-like. ~= réapparait plus tard dans Lua.
Assignement et déclaration
Assignements:
a := 10;
a := b := c := 10; // 10 assigné à a, b et c.
a +:= b; // équivalent à a := a + b
On peut remplacer + par tout autre opérateur arithmétique.
Déclarations:
int i = 10;
real r = 1.2;
[]int ai = (2,5,89,6,3);
[]string astr = ("a", "b", "hello");
[1:2,4:5]int mi = ((10,20), (100,200)); // Tableau à deux dimensions.
Constante et variable
int i = 10;
int j := 20;
i est une constante alors que j est une variable. Cela n'a été repris dans aucun autre langage.
Indexation et tranches
[]int ai = (10,20,30,40,50);
ai[2] retourne 30.
ai[2 : 3] retourne 40,50.
Le langage dispose d'un syntaxe complexe pour accéder au contenu d'un tableau à plusieurs dimensions, ou d'une chaîne de caractères qui complique bien inutilement la réalisation d'un compilateur.
Tableau dynamique
Le modifieur flex permet de définir un tableau comme étant de taille variable.
Structure
La déclaration est similaire à l'en-tête d'une fonction.
struct (int i, real r) s;
i of s := 10;
r of s := 1.23;
L'équivalent C serait:
struct s {
int i = 10;
real r = 1.23;
}
Pascal a choisi d'utiliser le construct record, qui vient d'ALGOL 60, qui l'a hérité lui-même de COBOL. Les deux sont des types complexes et les ancêtres des classes.
Union
Dans une union, les variables partagent la même zone de mémoire et une même valeur peut donc être accessible avec des types différents.
union(int i, real r) u;
Structure de contrôle if
Le terminateur est le mot if à l'envers. Une syntaxe étrange que l'on ne retrouve dans aucun autre langage qui a suivi, pas même dans Pascal.
if condition then
...
[else ... ]
fi
ou
if condition then
...
elif condition then
...
[else ...]
fi
Structure de contrôle for
Elle fait beaucoup de choses à la fois.
for variable from debut [by increment] to fin [while condition] do
...
od
Exemple:
for i from 1 to 10 while i ne 11 do
...
od
Les différents parties sont optionnelles. Par exemple
to 10 do ... od
exécute dix fois la boucle. Alors que:
for i while i < 11 do ... od
exécute la boucle tant que la condition est satisfaite.
La tendance a été ensuite de diviser la structure en plusieurs autres: for, while, do until, for in. Cependant le langage Go est revenu à cettre structure à tiroirs.
Foreach a été ajouté plus tard à ALGOL 68 par des compilateurs.
Structure de contrôle case
L'ancêtre de la structure de contrôle switch case était plus limité:
case variable in
instructions,
instructions,
...
esac;
Exemple pour le nombre de jour dans les mois d'une année, de janvier à décembre.
La variable mois à une valeur de 1 à 12.
case mois in
31,
if annee % 4 = 0 and année % 100 ~= 0 or annee % 400 = 0 then 29 else fi;
31,30,31,30,31,31,30,31,30,31
esac;
Procédure
Le type de retour est placé à la fin de l'en-tête, à l'inverse de C et on retrouve cela dans certains langages modernes, cela vient d'ALGOL.
proc p = (int a, real b) real:
begin
...
end;
Les paramètres sont entre parenthèses, le type de retour est placé ensuite.
La valeur de retour est la valeur de la dernière expression évaluée dans le corps de la procédure. Une idée reprise par le langage Julia.
Format d'une procédure sans paramètre et qui ne retourne rien:
proc q = void:
begin
...
end;
Pascal a cru bon de compliquer les choses en différenciant les fonctions qui retournent une valeur et les procédures qui ne retournent rien, une dualité qui existe aussi dans Fortran. C'est une régression et cela n'apporte rien. D'ailleurs une routine de Fortran peut retourner plusieurs valeurs à la fois ce qui manque à Pascal.
Concurrence
Des procédures peuvent être exécutées en parallèle avec la commande par:
par begin
...
end;
Les coroutines de Go sont assez similaires.
Conclusion
Le langage semble avoir été défini par un groupe de discussion où chacun veut apporter ses idées pour compléter le langage et ou personne ne se soucie de la construction du compilateur qui va l'implémenter. Cela a incité Niklaus Wirth, pour obtenir un compilateur performant, à créer Pascal sur la base d'ALGOL mais en se débarrassant d'une grande partie des éléments du langage.
Cependant, beaucoup des concepts présents dans ALGOL se retrouvent dans les languages qui lui ont succédé, et certains qui ont été abandonnés réapparaissent dans des langages récents comme Go, Julia. A l'inverse, la syntaxe différente et les concepts d'autres langages anciens comme Tcl, Rebol, etc... sont tombés dans l'oubli.
Références: