• Aucun résultat trouvé

Nous avons vu dans ce chapitre comment filtrer uniform´ement sur de nombreuses structures de donn´ees, y compris des structures non-alg´ebriques. Ceci permet notamment de g´erer fonc-tionnellement ces structures. Avoir consid´er´e les collections d’un point de vue topologique nous permet d’uniformiser le filtrage et de donner un sens `a un mˆeme motif sur toute collection.

Dans le but d’ˆetre efficace, on n’impl´ementera pas le filtrage par l’algorithme tel qu’il est propos´e. Celui-ci peut ˆetre vu comme une sp´ecification de l’op´eration de filtrage. Nous verrons dans le chapitre consacr´e `a la compilation des m´ethodes de filtrage plus efficaces. Toutefois cet algorithme a l’avantage de s’adapter `a toute collection topologique. Ainsi on peut ajouter `a MGS de nouveaux types de collections sans avoir `a fournir d’algorithme sp´ecialis´e pour ceux-ci.

SK-traduction au vol en pr´esence de

traits imp´eratifs

Les travaux pr´esent´es dans ce chapitre ont ´et´e publi´es dans [Coh05].

Dans ce chapitre nous exposons certaines des techniques utilis´ees pour l’impl´ementation de l’interpr`ete MGS. Nous nous concentrons sur la r´ealisation de l’´evaluateur qui est le module d´edi´e `a l’interpr´etation du noyau fonctionnel du langage. L’originalit´e de cette impl´ementation est qu’elle repose sur la r´eduction de l’application du langage hˆote au lieu de la g´erer elle-mˆeme. Un objectif de simplicit´e, d’orthogonalit´e et d’efficacit´e a motiv´e ce choix. Nous utilisons une technique de combinatorisation afin de transformer les fonctions d´efinies par l’utilisateur en fonctions du langage hˆote. Les fonctions non-strictes et les traits imp´eratifs de MGS sont bien int´egr´es `a ce sch´ema grˆace `a l’utilisation de gla¸cons. Nous serons donc amen´es `a ´etudier la combinatorisation SK en pr´esence de traits imp´eratifs.

La section V.1 d´etaille les raisons qui nous ont pouss´es `a choisir cette approche. Nous in-troduisons dans la section suivante une impl´ementation classique d’un interpr`ete puis nous la comparons `a l’approche d’ordre sup´erieur en section V.3. La r´ealisation de notre approche par syntaxe d’ordre sup´erieur et combinatorisation est pr´esent´ee en section V.4. Elle est ensuite ´etendue aux fonctions non-strictes (section V.5) et aux traits imp´eratifs (section V.6). Les sec-tions V.7 et V.8 concluent ce chapitre en indiquant que la preuve de correction reste `a ´etablir et en dressant un bref bilan.

V.1 Objectifs et motivations

Dans ce chapitre, nous ´etudions comment repr´esenter une valeur fonctionnelle MGS par une valeur fonctionnelle du langage qui sert `a impl´ementer notre interpr`ete (ici OCaml). Ce type de repr´esentation simplifie beaucoup l’´ecriture de l’interpr`ete et rel`eve de plusieurs domaines de recherche dont la logique combinatoire et la syntaxe abstraite d’ordre sup´erieur.

Trois probl`emes se posent avec cette approche :

1. La seule mani`ere de construire une valeur fonctionnelle comme r´esultat d’un calcul en Caml est par application de fonctions. Or les valeurs fonctionnelles en MGS peuvent se d´enoter en utilisant une abstraction. Il faut donc pouvoir construire la fonction d´efinie par cette abstraction uniquement par des applications. Ce point est r´esolu grˆace `a la traduction en

86 SK-traduction au vol en pr´esence de traits imp´eratifs

combinateurs.

2. Certaines expressions MGS correspondent `a des fonctions non-strictes alors que le langage d’impl´ementation n’a que des fonctions strictes et `a appel par valeur. La conditionnelle if-then-else, la conjonction logique et la disjonction sont des exemples de fonctions non-strictes. La solution est l’utilisation de gla¸cons.

3. MGS comporte des traits imp´eratifs. Or il est d´elicat de mixer certains traits imp´eratifs avec le s´equencement des calculs induit uniquement par les appels fonctionnels (par exemple, comment r´ealiser le s´equencement de deux ´evaluations quand on ne dispose que d’applica-tions de foncd’applica-tions et que l’ordre d’´evaluation des arguments n’est pas sp´ecifi´e ?). L`a aussi, la solution passe par l’utilisation de gla¸cons.

Si l’´evaluation d’un noyau fonctionnel dans un interpr`ete est un probl`eme classique, l’approche adopt´ee ici est assez peu habituelle. Cependant, elle r´epond aux six contraintes suivantes qui ont ´et´e pos´ees a priori dans le cadre du projet MGS :

1. Nous voulons un sch´ema d’´evaluation interpr´et´e.

MGS est d´edi´e au prototypage rapide de mod`ele de simulation. Cette activit´e demande de nombreux aller-retours entre les phases de conception du mod`ele et l’ex´ecution de la simulation proprement dite. Un interpr`ete et un sch´ema d’´evaluation dynamique sont bien mieux adapt´es `a ce type d’activit´e qu’un compilateur. La compilation de MGS est un probl`eme abord´e dans la suite de ce document mais nous voulons disposer des deux outils.

2. L’´evaluateur doit pouvoir s’impl´ementer indiff´eremment dans tout langage « raisonnable ». Afin de faciliter sa diffusion, en particulier aupr`es des non-informaticiens, l’interpr`ete MGS doit pouvoir ˆetre (et a ´et´e effectivement) port´e sur des environnement diff´erents (sous Windows/Cygwin et sous MAC OS X). Par ailleurs MGS est un langage exp´erimental et plusieurs versions ont ´et´e d´evelopp´ees (dont une en C++). Enfin, nous ne voulons pas que l’impl´ementation puisse d´ependre de sp´ecificit´es du langage d’impl´ementation.

Si nous utilisons OCaml comme langage d’impl´ementation notre approche doit rester va-lable pour un autre langage. On verra que la strat´egie d’´evaluation d´evelopp´ee dans ce chapitre ne requiert que la possibilit´e de passer des fonctions en param`etre `a une autre fonction et de retourner des fonctions comme r´esultat d’une application de fonction.

3. L’´evaluateur doit rester simple (tout au plus quelques centaines de lignes de code) et extensible, tout en offrant des structures de contrˆole utiles comme les exceptions et des outils de trace et de d´ebug.

Bien que nous ne le d´etaillerons pas, l’introduction dans MGS d’un m´ecanisme d’exception `a la OCaml et de possibilit´es de trace des appels de fonctions est r´ealis´ee par moins d’une cinquantaine de lignes de code `a partir du sch´ema d’´evaluation propos´e dans ce chapitre.

4. La performance n’est pas le souci premier, mais l’´evaluateur doit n´eanmoins ˆetre le plus efficace possible sans sacrifier l’extensibilit´e et la simplicit´e du sch´ema d’´evaluation adopt´e. Notre objectif est d’ˆetre plus efficace que Mathematica (pour la partie fonctionnelle et le filtrage) et au moins aussi efficace que Python (sur l’aspect fonctionnel).

5. Le sch´ema d’´evaluation adopt´e doit permettre le d´eveloppement et l’int´egration imm´ediate de librairies d´evelopp´ees dans le langage d’impl´ementation et l’int´egration de librairies d´evelopp´ees dans un autre langage (comme C et C++).

Ces librairies correspondent au d´eveloppement des collections topologiques offertes par MGS. Elles doivent donc ˆetre efficaces (en espace et en temps) et il est donc sage de pouvoir les compiler. De plus, les d´eveloppements logiciels impliqu´es peuvent ˆetre lourds. Ces librairies doivent donc pouvoir se concevoir et se d´evelopper de mani`ere compl`etement ind´ependante de l’impl´ementation de l’´evaluateur proprement dit.

6. La notion de fonction offerte par le langage doit ˆetre uniforme.

En particulier, un programmeur MGS ne doit pas pouvoir distinguer une fonction qu’il a ´ecrit lui-mˆeme en MGS d’une fonction « primitive » impl´ement´ee par une des librairies ´evoqu´ees dans le point ci-dessus. Ainsi, une op´eration primitive d’ordre sup´erieur doit pouvoir accepter en argument aussi bien une fonction ´ecrite par l’utilisateur en MGS qu’une autre primitive pr´ed´efinie, et cela de mani`ere transparente aussi bien pour le concepteur de la librairie que pour le programmeur MGS. C’est une propri´et´e forte, difficile `a assurer, mais qui permet d’´ecrire simplement des librairies puissantes, facilement param´etrables et extensibles.

Les points 2 et 5 nous font renoncer aux approches de type « traduction au vol vers un langage interpr´et´e » comme celle permise par Camlp4 [dR02]. La contrainte 3 exclue les approches de type « compilation vers une machine virtuelle », du moins si l’on veut que le r´esultat soit rai-sonnablement efficace1. La contrainte 6 ne peut pas ˆetre assur´ee par les approches classiques par ´evaluation des termes comme d´ecrit `a la section V.2.

En fait, prise au sens litt´eral, cette derni`ere contrainte impose que les fonctions ´ecrites par le programmeur MGS soient traduites au vol en des fonctions du langage d’impl´ementation. Cependant, puisque le langage d’impl´ementation est compil´e, cela n’est possible que si les fonc-tions sont des valeurs (ce n’est par exemple pas le cas en Fortran77 mais c’est le cas en C ou en OCaml) puisque les seules entit´es qui peuvent se construire lors de l’ex´ecution sont des va-leurs. Les op´erations permettant de construire des valeurs fonctionnelles dans un langage de programmation ne sont pas nombreuses. Nous ne voulons pas bien sˆur embarquer de mani`ere plus ou moins explicite un interpr`ete du langage d’impl´ementation dans l’interpr`ete MGS. La logique combinatoire offre alors une solution : toute fonction peut se construire comme r´esultat de l’application d’un jeu r´eduit de fonctions primitives : les combinateurs.

L’id´ee originale d´evelopp´ee dans ce chapitre est de faire reposer l’´evaluation du noyau fonc-tionnel du langage source uniquement sur le m´ecanisme d’application de fonction du langage d’impl´ementation et d’associer dynamiquement `a chaque fonction ´ecrite dans le langage source, une fonction du langage d’impl´ementation calcul´ee dynamiquement dans l’interpr`ete.

Cette approche est tr`es diff´erente des approches d’´evaluation par r´eduction de combina-teurs propos´ee par [PJ87] et d´evelopp´ees notamment dans [JS89, Hug82] (et qui rel`event de la cat´egorie des machines virtuelles) ou de la construction d’un r´eseau de fermetures dans [FL87], qui ne permet pas de faire abstraction des manipulations explicites d’environnements. A notre connaissance, l’approche que nous d´ecrivons dans ce chapitre est nouvelle et mixe des id´ees is-sues des travaux sur la « syntaxe abstraite d’ordre sup´erieur » avec des notions emprunt´ees `a la logique combinatoire.

Organisation du chapitre. Dans la suite de ce chapitre, nous ´etudions un sch´ema d’´evaluation qui satisfait les contraintes d´ecrite ci-dessus. Nous ne consid´erons pas ici les transformations ni le filtrage car ces m´ecanismes sont ind´ependants du probl`eme pos´e et sont trait´ees `a un autre niveau. Notons toutefois que les gardes des motifs et les parties droites des r`egles de transfor-mations sont vues comme des fonctions des valeurs filtr´ees et sont donc trait´ees uniform´ement selon le sch´ema que nous pr´esentons ici.

1

Une version de MGS a ´et´e d´evelopp´ee avec un ´evaluateur correspondant `a la machine virtuelle SECD [Lan65a]. Cette approche s’est r´ev´el´ee moins efficace que l’approche par interpr´etation directe des termes, comme d´ecrit `a la section V.2, du moins tant que l’on en restait `a une compilation directe sans optimisation particuli`ere. Ce sch´ema d’´evaluation ne r´epondait pas non plus aux contraintes 5 et 6.

88 SK-traduction au vol en pr´esence de traits imp´eratifs

Le reste du chapitre s’organise comme suit. Nous commen¸cons par donner une mani`ere classique d’impl´ementer un interpr`ete (section V.2) puis nous ´evoquons l’approche par syntaxe abstraite d’ordre sup´erieur (section V.3). Ensuite nous d´etaillons comment la combinatorisation permet d’utiliser une syntaxe d’ordre sup´erieur (section V.4). Dans les sections V.5 et V.6 nous ´etudions comment introduire les fonctions non-strictes et les traits imp´eratifs dans ce sch´ema d’´evaluation en utilisant des gla¸cons. Notons d`es `a pr´esent que le chapitre suivant est consacr´e aux optimisations que l’on peut apporter `a ce sch´ema.