Projet Cristal

previous up next contents
Précédent : Présentation générale et objectifs Remonter : Projet CRISTAL, Programmation typée, modularité Suivant : Grands domaines d'application



Fondements scientifiques

Systèmes de types

Typage: Discipline de programmation visant à vérifier et garantir l'utilisation cohérente des données manipulées dans les programmes.
Typage statique ou dynamique: Lorsque cette vérification est effectuée avant l'exécution du programme (généralement par le compilateur), on dit que le typage est statique. Lorsqu'elle a lieu à l'exécution, la vérification est dite dynamique.
Synthèse de types: On dit que les types des programmes sont synthétisés (ou encore inférés) lorsque l'on n'impose pas au programmeur de spécifier les types de toutes les expressions du programme.
Polymorphisme: Un type est dit polymorphe lorsque certaines de ses composantes sont variables, et représentent toute une famille de types (obtenus par instanciation de ces variables).
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.

Synthèse de types de ML

 Le langage ML dispose, depuis sa conception en 1978, d'un système de types autorisant la synthèse automatique des types à la compilation, ainsi que d'une forme de polymorphisme permettant la programmation d'algorithmes génériques (i.e. travaillant sur toute une variété de données de types différents). Le système de types de ML est spécifié formellement, et un théorème énonce sa propriété principale: aucune erreur de type ne peut se produire à l'exécution.

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.

Typage des objets

 La programmation par objets connaît un succès important depuis plusieurs années, mais peu de langages disposent d'une sémantique clairement et formellement établie. Diverses approches ont été utilisées avec pour but d'établir les fondements de la programmation par objets en termes de théorie des types.

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.

Types intersection

 Les types intersection jouent un rôle fondamental dans la théorie des langages typés et ont été abondamment étudiés sur le plan théorique. Leur puissance d'expression est telle qu'ils permettent de caractériser les propriétés de terminaison de l'évaluation des termes du lambda-calcul, et ont été utilisés comme fondements d'autres systèmes de types (par exemple des systèmes de types pour la programmation impérative ou par objets).

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.

Typage et analyses statiques

  Il est aussi possible d'aborder l'analyse et la compilation optimisante de programmes en utilisant des techniques qui relèvent du typage. C'est le cas de l'analyse d'exceptions, qui devrait fournir à l'usager, dès la compilation, des informations précieuses sur les erreurs qui peuvent être déclenchées durant l'exécution des programmes. François Pessaux effectue une thèse sur ce sujet. De même, les informations fournies par le typage statique sont une aide précieuse pour produire du code efficace lors de la compilation. Xavier Leroy a ainsi développé des techniques de représentations efficaces de structures de données qui reposent de manière essentielle sur le typage statique.

Typage et sécurité

  L'effervescence autour du code mobile et la programmation des cartes à puce suscite un regain d'intérêt pour la sûreté et la sécurité des programmes. Les méthodes de typage fournissent un angle nouveau pour aborder ces problèmes dans ce contexte. Le travail de Xavier Leroy et François Rouaix constitue une première approche et ouvre une voie vers des techniques formelles pour développer et valider des environnements d'exécution sûrs pour des applets dans un langage fortement typé.

Le langage Caml

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.


Parmi les développements du projet Cristal, le langage Caml [WL93] joue un rôle important. L'équipe en tire en effet des sujets de recherche, l'utilise comme champ d'expérimentation et de validation, ainsi que comme moyen de transfert et de diffusion de nos résultats.

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).



previous up next contents Précédent : Présentation générale et objectifs Remonter : Projet CRISTAL, Programmation typée, modularité Suivant : Grands domaines d'application