XL (eXtensible Language) | |
Apparu en | 2000 |
---|---|
Développeur | Christophe de Dinechin |
Dernière version stable | 0.1 (2010)[+/−] |
Paradigmes | Programmation impérative |
Typage | Fort |
Influencé par | Ada, C++ |
Système d'exploitation | Type Unix |
Licence | GPL |
Site Web | XLR |
XL, dont les lettres proviennent de eXtensible Language, est un langage de programmation, basé sur la programmation par concepts, développé depuis 2000 par Christophe de Dinechin.
XL offre la possibilité de modifier et programmer la syntaxe et la sémantique du langage. Des plugins compilés peuvent être utilisés pour ajouter de nouvelles fonctionnalités au langage. On peut par exemple noter un ensemble de plugins permettant la mis en œuvre d'un langage impératif. Les utilisateurs peuvent écrire eux-même leurs propres plugins pour permettre l'utilisation de syntaxe spécifiques, par exemple pour la dérivée, qui pourront être utilisés de la même manière que les fonctionnalités originales.
XL est défini en quatre niveaux différents :
XL n'a ni type primitif ni mot-clé. Tous les opérateurs et les types de données, tels que les entiers ou les additions, sont définis dans la librairie standard XL2. XL1 est portable dans différents environnements d'exécution. Ce qui n'est pas garanti pour XL2 qui n'offre pas de tels garanties : si un processeur particulier n'implémente pas la multiplication en virgule flottante, la définition de l'opérateur correspondant peut être manquante de la librairie standard, et l'utilisation de cette fonctionnalité peut générer une erreur de compilation.
En XL, le programme Hello World peut s'écrire ainsi :
use XL.TEXT_IO WriteLn "Hello World"
Une manière plus convenable pour des programmes plus importants serait :
import IO = XL.TEXT_IO IO.WriteLn "Hello World"
Une implémentation par récurrence de la fonction factorielle :
0! -> 1 N! -> N * (N-1)!
Le niveau XL1 est défini comme une une séquence d'opérations sur l'arbre syntaxique du niveau XL0. Ces opérations sont effectuées par divers plugins du compilateur qui sont appelés suivant la forme de l'arbre syntaxique.
Des constructions particulières, translate
et translation
, sont fournies par un plugin destiné à faciliter l'écriture d'autres plugins. La construction quote
génère un arbre syntaxique. Voici comment ces constructions peuvent être utilisées pour implémenter un plugin nommé ZeroRemoval
, qui supprime les aditions et multiplications par zéro :
translation ZeroRemoval when 'X' + 0 then return X when 'X' * 0 then return parse_tree(0)
Un plugin peut être invoqué sur un fichier complet à partir de la ligne de commande, ou plus localement dans le source du code en utilisant la notation pragma, comme ici :
X:= {Differentiate} d(sin(omega * T) * exp(-T/T0)) / dT
Le niveau XL1 contient un grand ensemble de plugins, notamment XLSemantics
qui donne les abstractions communes telles que fonction, type de données et déclaration de variable et définition, et aussi les ordres de base de la programmation structurée que sont les boucles et les conditions.
XL1 contrôle le type statique, avec des possibilités de programmation générique qui vont au-delà de celles de C++ ou Ada. Les types comme les tableaux ou les pointeurs, qui sont des types primitifs en C++, sont déclarés dans une bibliothèque dans XL. Par exemple, le type d'un tableau d'une dimension peut être définit par :
generic [Item: type; Size: integer] type array
Un type générique validé est un type générique où une condition indique comment le type peut être utilisé. De tels types ne doivent pas avoir de paramètres génériques. Par exemple, on peut déclarer un type comme ordered
(ordonné) si un opérateur inférieur est présent :
// Un type est ordonné en présence d'un opérateur inférieur generic type ordered if A, B: ordered Test: boolean:= A < B
Il est alors possible de déclarer une fonction qui est implicitement générique puisque le type ordered
est lui-même ordonné.
// Function générique pour au moins un élément function Min(X: ordered) return ordered is return X
Ceci s'applique aussi aux types génériques qui ont des paramètres, comme array
. Une fonction calculant la somme des éléments dans un tableau peut s'écrire :
function Sum(A: array) return array.Item is for I in 0..array.Size-1 loop result += A[I]
Les fonctions peuvent être surchargées. Une fonction peut être déclarée avec un nombre variable d'arguments grâce au mot other
dans la liste des paramètres. Dans une telle fonction, other
permet de passer un nombre variable d'arguments à une autre fonction :
// Fonction générique pour le minimum de N éléments function Min(X: ordered; ...) return ordered is result:= Min(...) if X < result then result:= X
Quand ce genre de fonction est appelée, le compilateur invoque les fonctions de manière récursive pour correspondre à la liste :
// Exemple d'utilisation de la fonction Min précedente X: real:= Min(1.3, 2.56, 7.21) Y: integer:= Min(1, 3, 6, 7, 1, 2)
Les opérateurs peuvent être définis en utilisant la forme written
de déclaration de fonction. Voici un code qui déclare l'addition d'entiers :
function Add(X, Y: integer) return integer written X+Y
De telles formes écrites peuvent avoir plus de deux paramètres . Par exemple, une transformation de matrice linéaire peut s'écrire :
function Linear(A, B, C: matrix) return matrix written A+B*C
Une forme écrite peut utiliser des constantes, et ce type de forme est plus spécialisée que sans constantes. Par exemple :
function Equal(A, B: matrix) return boolean written A=B function IsNull(A: matrix) return boolean written A=0 function IsUnity(A: matrix) return boolean written A=1
Ce mécanisme est utilisé pour décrire tous les opérateurs de base. Une expression est progressivement réduite à des appels utilisant des formes écrites. Pour cette raison, ce mécanisme est appelé réduction d'expression plutôt que surcharge d'opérateur.
Les itérateurs de XL permettent de programmer à la fois des générateurs et des itérateurs.
import IO = XL.UI.CONSOLE iterator IntegerIterator (var out Counter : integer; Low, High : integer) written Counter in Low..High is Counter := Low while Counter <= High loop yield Counter += 1 // I doit être déclaré, car indiqué comme 'var out' dans l'itérateur // Une déclaration implicite de I comme entier est alors faite ici for I in 1..5 loop IO.WriteLn "I=", I