Précédent : Présentation générale et
objectifs Remonter : Projet CRISTAL, Programmation typée,
modularité Suivant : Grands domaines d'application
Résumé : Le typage est une discipline importante de la programmation: il permet de spécifier la cohérence des données manipulées par les programmes, et de définir certains mécanismes de structuration du code (fonctions ou procédures, objets, modules, surcharge) propres aux langages de haut niveau à même d'être utilisés pour la construction d'applications complexes.L'équipe Cristal étudie les systèmes de types et les méthodes formelles y afférant, avec pour objectif de permettre la conception de langages et autres outils de programmation sûrs et aux propriétés formellement établies.
Les langages de programmation de haut niveau aide à structurer le code par des constructions (fonctions/procédures, objets, surcharge, modules) dont la sémantique est intimement liée aux systèmes de types. En particulier, les systèmes de types servent de support à la détection (statique ou dynamique) d'erreurs de programmation.
Le projet Cristal étudie, sous l'angle des systèmes de types, les fondements de la programmation fonctionnelle, impérative, modulaire et par objets. Nous nous intéressons aussi bien aux aspects statiques que dynamiques des langages typés.
De par sa conception et sa généralité, le système de types de ML a servi de cadre d'étude à de nombreux travaux sur le typage:
Les résultats de nos recherches dans ce domaine, même si celles-ci ont une vocation plus générale, trouvent généralement des applications sur le langage Caml: une version de ML conçue et développée dans notre équipe.
Dans le domaine des systèmes de types, les sujets actuellement étudiés vont des fondements de la programmation par objets à la sécurité des programmes, en passant par le polymorphisme semi-explicite, et sont détaillés dans les sections suivantes.
L'une des approches que nous suivons au projet Cristal repose sur les travaux de Didier Rémy, qui a proposé dans sa thèse un système d'enregistrements extensibles supportant la synthèse de types. Après la conception et la réalisation d'une première maquette d'un système à objets pour ML appelé ML-ART [Rém94], Didier Rémy s'est attaqué à l'adjonction d'objets dans le langage Caml, devenu ainsi Objective Caml (OCaml). Cette couche à objets, s'appuyant sur des classes et compatible avec la synthèse de types polymorphes, est l'une des plus attrayantes parmi celles proposées pour les langages fortement typés, en dépit de la contrainte imposée par la synthèse des types. Par exemple, le système OCaml permet de typer des programmes réputés difficiles et rejetés par le langage Java, pourtant explicitement typé. C'est le cas notamment des programmes nécessitant, dans le jargon Java, des «types virtuels»; ce travail pourrait, en ce sens, servir de base à la formalisation des types virtuels de Java.
Une autre étude poursuivie est le sous-typage implicite, sujet de thèse de François Pottier, qui permettrait entre autre, de rendre OCaml encore plus performant et plus convivial. Une dernière approche explorée repose sur la surcharge d'identificateurs et le comportement de fonctions guidé par le type de leurs arguments: c'est le polymorphisme extensionnel, sujet de thèse de Jun Furuse.
Malheureusement, les présentations qui en sont faites sont généralement complexes et les algorithmes présentés ne sont pas effectifs. Émilie Sayag a terminé sa thèse sur ce sujet en 1997: elle présente un système qui permet de rapprocher le mécanisme de la synthèse de types intersection du processus de normalisation du lambda-calcul. Ce travail devrait servir de base à une meilleure compréhension de l'évolution dynamique des types statiques dans les langages de programmation dotés d'une discipline de typage polymorphe.
Styles de programmation et structuration des programmes: Les programmes s'écrivent dans des langages de programmation, et, peuvent être organisés et structurés selon des styles différents.
Le style fonctionnel tend à privilégier les fonctions, presque au sens mathématique du terme: un programme est une expression à évaluer qui fournit un résultat dépendant seulement des valeurs des paramètres d'entrée.
Plus classique, le style impératif privilégie l'exécution d'instructions qui modifie l'état de la machine (sa mémoire ou bien ses entrées-sorties).
Le style à objets favorise le regroupement de données, de leur état (sorte de mémoire privée) et de leurs comportements (méthodes) en des entités appelées objets. Afin de favoriser la réutilisation de code, la définition d'objets complexes utilise généralement un mécanisme qui leur permet d'hériter des fonctionnalités d'objets plus simples. Ce mécanisme est appelé héritage. De la sorte, seules les fonctionnalités nouvelles doivent être programmées. La programmation par objets rencontre un grand succès dans l'industrie du logiciel.
Le développement d'applications de grande taille nécessite
aussi la division des programmes en unités de taille raisonnable,
à mi-chemin entre la granularité fine des fonctions ou des
objets, et celle d'un gros programme monolithique: il s'agit des
modules, qui regroupent des sous-programmes appartenant à
une même entité logique.
Compilation et exécution: Un compilateur de langage de programmation traduit les programmes écrits dans ce langage en des instructions de plus bas niveau, interprétables par la machine. Les instructions peuvent être du bytecode fonctionnant sur une grande variété de machines, ou bien du code natif spécifique à l'architecture de la machine sous-jacente. Le bytecode peut être le même pour une grande variété d'architectures de machines et est interprété par un programme dédié. Le code natif est directement interprété par la machine, et dépend donc son architecture.
Le modèle d'exécution du langage est une vision
abstraite de l'exécution de ce code et de sa politique de gestion
de la mémoire.
Résumé : Le langage de programmation Caml est l'un des langages de la famille ML. Tout comme les autres versions de ML, Caml a été à la fois la source d'inspiration et l'objet de nombreuses recherches, et s'est souvent enrichi des solutions apportées, tant dans le domaine du typage que dans celui des modèles d'exécution.Autorisant les styles de programmation impératif, fonctionnel et par objets, dotée d'un puissant système de modules et d'un compilateur très performant, la dernière version de Caml développée au projet Cristal est nommée Objective Caml (OCaml) et constitue une base de développement d'applications réelles dans les domaines les plus divers.
Le langage Caml est l'héritier des premières versions de ML qui était le méta-langage de l'assistant de preuves LCF conçu par Robin Milner. ML était le langage dans lequel étaient programmées les tactiques de recherche de preuves de LCF.
Constitué initialement d'un noyau fonctionnel et de quelques traits impératifs, le langage ML connut des évolutions majeures au cours des années, tant du point de vue de ses caractéristiques que de l'efficacité de ses implémentations. En particulier, deux branches distinctes de ML sont apparues au milieu des années 80: l'une, nommée Standard ML, est le résultat du travail de conception et de définition de ML par un groupe à la tête duquel se trouvait Robin Milner. L'une des caractéristiques les plus novatrices de Standard ML était son système de modules.
Le langage Caml constitue l'autre branche de la famille des langages ML. Conçu et développé au projet Formel à l'INRIA, en collaboration avec des membres du Laboratoire Informatique de l'École Normale Supérieure de Paris, puis au projet Cristal, Caml a lui aussi connu des évolutions importantes.
Les recherches menées au projet Cristal ont conduit à
l'adjonction au langage Caml de traits importants comme les
modules et les objets. En effet, ces deux façons de structurer
les programmes ont dû être l'objet de recherches intensives afin
d'être dotés de sémantiques statiques (typage) et dynamiques
(exécution) clairement définies et prouvées correctes. Les objets
ont été étudiés par Didier Rémy (cf. section ). Les modules ont été étudiés
par Xavier Leroy [Ler96], qui a étendu et
simplifié le système de modules de Standard ML afin de le rendre
compatible avec la compilation séparée. (Modularité et
compilation séparée sont deux éléments essentiels du
développement logiciel à grande échelle.)
La version de Caml incorporant tous ces traits est nommée Objective Caml.
Du point de vue de l'implémentation, le langage Caml a donné lieu à des recherches sur les modèles d'exécution des langages fonctionnels. Le modèle d'exécution de Caml, initialement basé sur la Machine Abstraite Catégorique (CAM) et s'appuyant sur la machine LLM3 de Le-Lisp (de l'INRIA), a été changé en machine virtuelle bytecodée avec l'implémentation Caml-Light [LW93]. Cette implémentation, réalisée par Xavier Leroy, et s'appuyant sur un gestionnaire de mémoire dû à Damien Doligez [DL93] a été conçue de sorte à être portable et économe en ressources mémoire. Lors du passage de Caml Light à Objective Caml, Xavier Leroy a intégré un compilateur produisant du code natif performant qui, allié au générateur de bytecode, permet dorénavant de disposer du meilleur des deux mondes: portabilité et cycle de développement rapide grâce au bytecode, et code natif très efficace avec le compilateur optimisant (disponible pour les architectures les plus courantes).