Docstoc

Mandel-These

Document Sample
Mandel-These Powered By Docstoc
					                   ´
          UNIVERSITE PARIS 6 – PIERRE ET MARIE CURIE


                                           `
                                         THESE

                                  pour obtenir le grade de

                                              ´
                        DOCTEUR de l’UNIVERSITE PARIS 6

                                e      e
                              Sp´cialit´ : INFORMATIQUE



                                        e    e
                                      pr´sent´e par :

                                    Louis Mandel




                 e
    Conception, S´mantique et Implantation de
                   ReactiveML :
           a                              e
un langage ` la ML pour la programmation r´active



                                e        e
                              Th`se dirig´e par Marc Pouzet



                                             e
Soutenue le 22 mai 2006 devant le jury compos´ de :
 Rapporteurs
   M. Fr´d´ric Boussinot
         e e                   ıtre
                            Maˆ de Recherche                  Ecole des Mines de Paris
                    ´
   M. Jean-Jacques Levy     Directeur de Recherche            INRIA Rocquencourt
 Examinateurs
   M. G´rard Berry
        e                   Directeur Scientifique             Esterel Technologies
   Mme. Florence Maraninchi Professeur                        ENSIMAG-INPG
   M. Jean-Charles Pomerol  Professeur                                 e
                                                              Universit´ Paris 6
                e
 Directeur de th`se
   M. Marc Pouzet           Professeur                                 e
                                                              Universit´ Paris-Sud 11
                             Remerciements

                              `               e                                     e
    En premier lieu, je tiens a remercier sinc`rement Jean-Charles Pomerol, Pr´sident de l’uni-
      e                                                                        e
versit´ Pierre et Marie Curie, de m’avoir fait l’honneur de bien vouloir pr´sider le jury de ma
  e
th`se.
                   e e                                  e                  e e
    Je remercie Fr´d´ric Boussinot et Jean-Jacques L´vy d’avoir accept´ d’ˆtre rapporteurs de
       e
ma th`se.
                                                                          e
    De par sa grande culture scientifique et sa rigueur, c’est un privil`ge d’avoir eu le regard
                            e
critique de Jean-Jacques L´vy sur mon travail.
                                                           e e                    `
    L’approche originale des langages synchrones de Fr´d´ric Boussinot est a la base de mes
                                                                                   e
recherches. Je souhaite le remercier pour sa gentillesse et pour les discussions tr`s enrichissantes
que nous avons eues.
             `                                    ` e
    Je tiens a exprimer ma profonde gratitude a G´rard Berry et Florence Maraninchi qui me
                              `                 e
font l’honneur de participer a mon jury de th`se.
                                                   e
    Marc Pouzet m’a conduit sur ce sujet qui, apr`s plus de trois ans de recherche, me passionne
                                                   u
toujours autant. Sa rigueur scientifique et son goˆt pour le travail sont des exemples pour moi.
         `
Je tiens a lui exprimer toute ma reconnaissance pour sa direction attentive et exigeante, pour
               e                                                                  `
sa disponibilit´ et son soutien constant qui m’ont permis de mener ce travail a son terme.
                                                                  e` e
   Les premiers utilisateurs de ReactiveML ont beaucoup contribu´ a l’´volution du langage
              e               `
par leurs exp´riences ; merci a Farid Benbadis, Matthieu Carlier, Thomas Doumenc, Alain
Girault, Sarah Maarek, Lionel Morel, Ludovic Samper.
                       ee                                         e                     ee e
     Je remercie Th´r`se Hardin de m’avoir accueilli dans le th`me SPI du LIP6, il a ´t´ tr`s
    e                                          e             `                           e`
agr´able et stimulant de travailler avec cette ´quipe. Merci a Renaud Rioboo qui m’a form´ a la
  e                                          e e           e    `
d´marche scientifique pendant les stages pr´c´dant ma th`se ; a Damien Doligez et Pierre Weis
                      e        `
qui ont toujours r´pondu a mes questions sur OCaml lors de leurs visites hebdomadaires ; a    `
                                                                                   a
David Massot, Thierry Lanfroy et Catherine Abiven pour leur aide dans toutes les tˆches admi-
               `                    e                           e
nistratives ; a Pascal Cuoq et Gr´goire Hamon qui m’ont fait d´couvrir les langages synchrones
                 e          e                       e
et m’ont vant´ les qualit´s de leur directeur de th`se.
                                                                             e
     J’ai eu le plaisir de partager mon bureau au LIP6 avec des membres du th`me CALFOR. Je
                                                                   e              e
les remercie pour leur bonne humeur pendant les moments de d´tente et particuli`rement mes
    e                                                      e e            e e
coll`gues de bureau : Abdolali Basiri, Magali Bardet, Gw´nol´ Ars, et Gu´na¨l Renault sur qui
j’ai toujours pu compter pour me tenir compagnie pendant les week-ends au labo.
    Je remercie vivement Nicolas Halbwachs, Florence Maraninchi et Joseph Sifakis qui m’ont
                                  u                                              e
accueilli au laboratoire Verimag o` je poursuis actuellement mes recherches en pr´-post-doc et
                                    e                                         `
qui m’ont permis de terminer ma th`se dans de bonnes conditions. Merci aussi a l’ensemble des
                                                                              e
membres du laboratoire pour ce qu’ils m’apprennent au quotidien sur les syst`mes embarqu´s  e
et sur la montagne.

                                                 3
4

                 e                                       e
    Je souhaite ´galement remercier les membres de l’´quipe MIMOSA de l’INRIA Sophia-
                  e                                    c                                e
Antipolis et de l’´quipe voisine AOSTE qui m’ont re¸u chaleureusement pendant deux s´jours
        e                                         `                    e
et aupr`s desquels j’ai beaucoup appris. Je tiens a remercier particuli`rement Jean-Ferdinand
                                    e           e
Susini pour nos discussions passionn´es sur le r´actif.
                                                                e
     Merci aux membres de l’UFR d’informatique de l’universit´ Paris 7 avec qui j’ai eu l’occasion
                                                       `                                 e
de travailler pendant mon monitorat, en particulier a Olivier Carton qui m’a encadr´ et dont
          e                                                                 e          `
j’ai retir´ beaucoup d’enseignements lorsque je l’assistais en TD. Je tiens ´galement a exprimer
                `          e                      e            e        e
ma gratitude a Michel L´vy de m’avoir accept´ dans son ´quipe p´dagogique de logique et
                         `          e
programmation logique a l’universit´ Grenoble 1.
        e                                     ee                                e
    La r´alisation de ce travail n’aurait pas ´t´ possible sans des moments de d´tente, ainsi je
                                                                                  ee
dois remercier Vladimir, Yann, Olivier, Lætitia(s), Vincent, Myriam, Manuel, Th´r`se, Xavier,
                                              e
Elvire, Farid, Cletol, Ludovic, Mathias, Am´lie, Hugo, Lionel, . . .
                                                                           e             e
    Enfin je remercie naturellement ma famille pour son soutien et particuli`rement mon fr`re
                                         e                              e                 e
Charles qui a eu le courage de relire int´gralement ce document et ma m`re qui s’est occup´e
        e
de la pr´paration de la soutenance.
                                      e
                        Table des mati`res


              e
Table des mati`res                                                                                                                                 5


I                  e
     Contexte et pr´sentation du langage                                                                                                           9

1 Introduction                                                                                                                                    11
              e       e
  1.1 Les syst`mes r´actifs . . . . . . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   11
              e
  1.2 Le mod`le synchrone . . . . . . . . . . .       .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   12
              e e              e e
  1.3 Le mod`le r´actif de Fr´d´ric Boussinot         .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   16
       ´
  1.4 Etat de l’art . . . . . . . . . . . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   19
  1.5 ReactiveML . . . . . . . . . . . . . . . .      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   25
                    e
  1.6 Plan de la th`se . . . . . . . . . . . . . .    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   26

     e
2 Pr´sentation de ReactiveML                                                                 27
        e          `
  2.1 Pr´sentation a travers des exemples simples . . . . . . . . . . . . . . . . . . . . . 27
  2.2 Deux exemples complets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35


II       e
     La s´mantique de ReactiveML                                                                                                                  43

   e
3 S´mantique comportementale                                                                                                                      45
  3.1 Le noyau du langage . . . . . . . . . . . .         .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   45
                                              e
  3.2 Identification des expressions instantan´es          .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   48
       e          `
  3.3 S´mantique a grands pas . . . . . . . . . .         .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   49
        e                    e
  3.4 D´terminisme et unicit´ . . . . . . . . . .         .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   59
  3.5 Conclusion . . . . . . . . . . . . . . . . .        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   62

   e             e
4 S´mantique op´rationnelle                                                                                                                       65
       e          `
  4.1 S´mantique a petits pas . . . . . . . . . . . . . .                 .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   65
      ´                    e
  4.2 Equivalence avec la s´mantique comportementale                      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   68
                                    e
  4.3 Ajout des constructions non d´terministes . . . .                   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   70
  4.4 Conclusion . . . . . . . . . . . . . . . . . . . . .                .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   73

5 Typage                                                                                                                                          75
  5.1 Extension du typage de ML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .                                                       75
  5.2 Preuve de sˆret´ du typage pour la r´duction → . . . . . . . . . . . . . . . . . .
                 u e                      e                                                                                                       78
  5.3 Pr´servation du typage pour la r´duction →eoi . . . . . . . . . . . . . . . . . . .
        e                             e                                                                                                           83

                                                5
6                                                      e
                                         Table des mati`res

III   Ordonnancement                                                                                                                                           87

       e                                      e     e
6 Une s´mantique efficace pour le mod`le r´actif I : Glouton                                                                                                     89
            e              e
  6.1 Les cl´s d’un interpr`te efficace . . . . . . . . . . . . . . . . .                                           .   .   .   .   .   .   .   .   .   .   .    89
                                    e
  6.2 Les groupes : le format d’ex´cution de Glouton . . . . . . .                                                .   .   .   .   .   .   .   .   .   .   .    92
      ´
  6.3 Evaluation . . . . . . . . . . . . . . . . . . . . . . . . . . . . .                                        .   .   .   .   .   .   .   .   .   .   .    97
                                         o
  6.4 Ajout des constructions de contrˆle . . . . . . . . . . . . . . .                                           .   .   .   .   .   .   .   .   .   .   .   103
  6.5 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . .                                          .   .   .   .   .   .   .   .   .   .   .   108

       e
7 Une s´mantique efficace pour le mod`le      e                      e
                                                                  r´actif II              :   Lk                                                              111
  7.1 Le langage avec continuation Lk . . . . .                   . . . . . .             .   . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   111
       e
  7.2 S´mantique . . . . . . . . . . . . . . . .                  . . . . . .             .   . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   113
                                       o
  7.3 Ajout des constructions de contrˆle . . .                   . . . . . .             .   . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   116
  7.4 Conclusion . . . . . . . . . . . . . . . .                  . . . . . .             .   . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   122

8 Implantation                                                                                                                                                125
  8.1 Compilation vers Lk . . . . . . . . . . . . .                       .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   125
  8.2 Implantation des combinateurs . . . . . . .                         .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   126
  8.3 Implantation en Ocaml . . . . . . . . . . .                         .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   129
                                        e
  8.4 Ajout de la suspension et de la pr´emption                          .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   135
                                     e e
  8.5 Implantation sous forme API g´n´rique . .                           .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   136
  8.6 Conclusion . . . . . . . . . . . . . . . . . .                      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   140


IV    Applications et performances                                                                                                                            141

                                                        e
9 Simulation de protocoles de routage dans les r´seaux mobiles ad                                                                 hoc                         143
                  e                e      a
  9.1 Le routage g´ographique bas´ sur l’ˆge . . . . . . . . . . . . . . . . .                                                    . . .       .   .   .   .   143
  9.2 Discussion du choix de ReactiveML pour implanter le simulateur .                                                            . . .       .   .   .   .   144
  9.3 Description du simulateur . . . . . . . . . . . . . . . . . . . . . . . .                                                   . . .       .   .   .   .   145
  9.4 Implantation en ReactiveML . . . . . . . . . . . . . . . . . . . . .                                                        . . .       .   .   .   .   146
  9.5 Analyse des performances du simulateur . . . . . . . . . . . . . . . .                                                      . . .       .   .   .   .   152
  9.6 Extensions dynamiques . . . . . . . . . . . . . . . . . . . . . . . . .                                                     . . .       .   .   .   .   153
  9.7 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .                                                  . . .       .   .   .   .   154


V     Discussions et conclusion                                                                                                                               157

10 Discussions                                                                                                                                                159
                                e
   10.1 Les compositions parall`les .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   159
               e
   10.2 Les pr´emptions . . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   161
   10.3 Les signaux . . . . . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   164
         e                   e e
   10.4 S´paration instantan´/r´actif     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   168

11 Extensions                                                                                      173
                     e
   11.1 Les scripts r´actifs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
   11.2 Interface avec d’autres langages . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176
                        e e
   11.3 Configurations ´v´nementielles . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178
     11.4 Filtrage de la valeur des signaux . . . . . . . . . . . . . . . . . . . . . . . . . . . 179
                                 e e
     11.5 La composition parall`le s´quentielle . . . . . . . . . . . . . . . . . . . . . . . . . 182
     11.6 Automates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183

12 Conclusion                                                                                      185
         e    e
   12.1 R´sum´ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
   12.2 Perspectives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188


VI     Annexes                                                                                   191

              ee
A Manuel de r´f´rence                                                                       193
  A.1 Le compilateur ReactiveML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193
                   e
  A.2 Syntaxe concr`te de ReactiveML . . . . . . . . . . . . . . . . . . . . . . . . . . . 194

   e
B S´mantique Rewrite                                                                             203


Index                                                                                            207


Bibliographie                                                                                    209
                                      e
                                 Premi`re partie

              e
Contexte et pr´sentation du langage

1   Introduction                                                                                                    11
                e       e
    1.1 Les syst`mes r´actifs . . . . . . . . . . . . . . . . . . . . . . .     . . . . .   .   .   .   .   .   .   11
                e
    1.2 Le mod`le synchrone . . . . . . . . . . . . . . . . . . . . . . .       . . . . .   .   .   .   .   .   .   12
                                        e
        1.2.1 La composition parall`le . . . . . . . . . . . . . . . . .        . . . . .   .   .   .   .   .   .   13
                                                    e
        1.2.2 Les communications et les probl`mes de causalit´ . . .  e         . . . . .   .   .   .   .   .   .   14
                e e              e e
    1.3 Le mod`le r´actif de Fr´d´ric Boussinot . . . . . . . . . . . .         . . . . .   .   .   .   .   .   .   16
                                          e
        1.3.1 Ajout de retard au mod`le synchrone . . . . . . . . . .           . . . . .   .   .   .   .   .   .   16
                                    e
        1.3.2 Absence d’hypoth`se sur les signaux . . . . . . . . . .           . . . . .   .   .   .   .   .   .   18
        ´
    1.4 Etat de l’art . . . . . . . . . . . . . . . . . . . . . . . . . . . .   . . . . .   .   .   .   .   .   .   19
                        e                                 e
        1.4.1 Les diff´rents travaux sur l’approche r´active . . . . .           . . . . .   .   .   .   .   .   .   19
        1.4.2 Autres approches pour la programmation des syst`mes       e        e
                                                                                r´actifs    .   .   .   .   .   .   23
    1.5 ReactiveML . . . . . . . . . . . . . . . . . . . . . . . . . . . .      . . . . .   .   .   .   .   .   .   25
        1.5.1 Les traits du langage . . . . . . . . . . . . . . . . . . .       . . . . .   .   .   .   .   .   .   25
        1.5.2 L’approche suivie dans ReactiveML . . . . . . . . . .             . . . . .   .   .   .   .   .   .   25
                      e
    1.6 Plan de la th`se . . . . . . . . . . . . . . . . . . . . . . . . . .    . . . . .   .   .   .   .   .   .   26

2      e
    Pr´sentation de ReactiveML                                                                                      27
            e        `
    2.1 Pr´sentation a travers des exemples simples . . . . . . . . . . .        . . . .    .   .   .   .   .   .   27
                 e                                            e
         2.1.1 D´finition de processus et composition parall`le . . . . .         . . . .    .   .   .   .   .   .   27
         2.1.2 Les communications . . . . . . . . . . . . . . . . . . . .        . . . .    .   .   .   .   .   .   29
                                      o
         2.1.3 Les structures de contrˆle . . . . . . . . . . . . . . . . .      . . . .    .   .   .   .   .   .   30
                             e          e
         2.1.4 Signaux valu´s et multi-´mission . . . . . . . . . . . . .        . . . .    .   .   .   .   .   .   32
                                               e         e
         2.1.5 Aspects dynamiques, ordre sup´rieur et ´chappement de                  e
                                                                                 port´e     .   .   .   .   .   .   34
    2.2 Deux exemples complets . . . . . . . . . . . . . . . . . . . . . .       . . . .    .   .   .   .   .   .   35
         2.2.1 Le banc de poissons . . . . . . . . . . . . . . . . . . . .       . . . .    .   .   .   .   .   .   35
                           ´        e
         2.2.2 Le crible d’Eratosth`ne . . . . . . . . . . . . . . . . . .       . . . .    .   .   .   .   .   .   38
                                     Chapitre 1

                                Introduction

                              e      e                          e
    La programmation de syst`mes r´actifs tels que les jeux vid´o, les interfaces graphiques ou les
      e                           a                           e
probl`mes de simulation est une tˆche complexe. La difficult´ provient d’une part des probl`mes e
                                                                             e
algorithmiques, d’autre part de la gestion de la concurrence entre les diff´rents composants du
    e                                                       e                             e
syst`me. Ainsi, les outils pour programmer ce type de syst`mes doivent permettre de d´crire et
                                  e                                 e
manipuler de structures de donn´es complexes et proposer des m´canismes de synchronisation
                                             e
et de communications entre processus parall`les.


1.1             e     e
        Les syst`mes r´actifs
                                                                                e
    En reprenant la terminologie introduite par Harel et Pnueli [53], les syst`mes transformation-
                     e                                            e
nels lisent une entr´e, effectuent un calcul et produisent un r´sultat. Des exemples typiques de
     e
syst`mes transformationnels sont les compilateurs ou les logiciels de calcul scientifique. Dans ces
     e                                                                 e      `            e
syst`mes, les communications avec l’environnement se font au d´but et a la fin de l’ex´cution.
                                      e e
Les langages de programmations g´n´ralistes comme C [60], Java [46] ou Ocaml [63] sont
       e `
adapt´s a la programmation de ces syst`mes.e
                              e     e
    Par opposition, les syst`mes r´actifs interagissent en continu avec l’environnement. L’en-
                    e            e                    e
vironnement peut ˆtre constitu´ de capteurs, d’op´rateurs humains ou d’autres programmes.
           e     c               e      e                                              e
Ces syst`mes re¸oivent des entr´es et ´mettent des sorties tout au long de leur ex´cution. Nous
                            e                           e                e           e
distinguons parmi ces syst`mes deux familles : les syst`mes temps-r´el et les syst`mes interactifs.
             e                  e                    e                 e
    Un syst`me est dit temps-r´el si le temps de r´action est inf´rieur au temps compris entre
                        e e                 e                 e                    e ` e
deux occurrences des ´v´nements d’entr´e. Ainsi, le syst`me est toujours prˆt a r´pondre aux
                                                  e                  e
sollicitations de son environnement. Ces syst`mes sont utilis´s dans le cadre d’applications
                                                                e                 e
critiques (ferroviaire, avionique). Pour garantir qu’un syst`me est temps-r´el, il faut pouvoir
  e                               e e                       e               e
v´rifier statiquement qu’il est ex´cut´ en temps et en m´moire born´s. Parmi les outils pour la
                          e            e                  e
programmation des syst`mes temps-r´el, nous nous int´resserons aux langages synchrones. Ces
               ee                         e
langages ont ´t´ introduits dans les ann´es 1980 avec Lustre [51], Signal [49] et Esterel [12].
                  e                                e            e          e                e
    Dans les syst`mes interactifs, la vitesse de r´action est d´termin´e par la vitesse de r´action
         e                                       e           e                    e
du syst`me. C’est par exemple le cas d’un syst`me de fenˆtrage dans un syst`me d’exploitation.
                                                           e                  e
Lorsqu’une commande telle que l’ouverture d’une fenˆtre est demand´e par l’utilisateur, le
     e               e
syst`me essaye de r´pondre le plus vite possible mais il n’y a pas de garantie sur le temps de
 e                                   e
r´ponse. Ce n’est donc pas un syst`me temps-r´el.  e
              e                                                     e             e
    Les syst`mes interactifs sont plus expressifs que les syst`mes temps-r´el car ils peuvent
e
´voluer dynamiquement en fonction des sollicitations de l’environnement. De nouveaux proces-
               e    ee              e                   e
sus peuvent ˆtre cr´´s ou supprim´s au cours de l’ex´cution du syst`me.    e

                                                11
12                                             1. Introduction

                                          e                            e
     Pour la programmation des syst`mes interactifs, les deux mod`les de programmation les
           e                      e e                            e                            e
plus utilis´s sont les boucles ´v´nementielles et les processus l´gers (plus couramment appel´s
threads).
                                                e                   u                     e e
     Les threads [61, 37] proposent un mod`le de concurrence o` les processus sont ex´cut´s
     e                                                                       e          e
ind´pendamment et les communications entre les processus se font par m´moire partag´e. Dans
         e                              e
ce mod`le, l’ordonnancement est pr´emptif et les synchronisations se font avec des primitives de
                                                e                                e `
synchronisation comme les verrous ou les s´maphores. Les threads sont adapt´s a la program-
                e      u
mation de syst`mes o` il y a peu de communications et de synchronisations entre les processus.
                               e
     Comme il est expliqu´ dans [82], il est difficile de programmer avec des threads. L’acc`s  e
`        e             e         e          e e             e                        e
a la m´moire partag´e doit ˆtre prot´g´ sinon les donn´es peuvent devenir incoh´rentes. Ces
   e                                      e
m´canismes de protection des donn´es peuvent introduire des interblocages. De plus, le non
  e                        e
d´terminisme rend le d´bogage difficile.
                           e e
     La programmation ´v´nementielle [44] (event-driven programming) est une autre approche
                                    e                        e                          e
pour la programmation de syst`mes interactifs. Ce mod`le de programmation est bas´ sur un
                         e       u                       o               u       e
ordonnancement coop´ratif o` chaque processus contrˆle le moment o` il peut ˆtre interrompu.
                   e                              e `      e e                     e e
     Dans ce mod`le, des actions sont attach´es a des ´v´nements. Une boucle ´v´nementielle
 e     e      e e                e                                                   e
r´cup`re les ´v´nements et d´clenche successivement les actions qui leur sont associ´es. Chaque
             e                     e                                     e e
action doit ˆtre de courte dur´e afin de ne pas bloquer la boucle d’´v´nements. C’est un des
        e
inconv´nients de ce mod`le.  e
                           e e                  e      e
     La programmation ´v´nementielle est tr`s utilis´e pour la programmation d’interfaces gra-
phiques. Par exemple la biblioth`que Gtk [48] utilis´ pour Gimp ou Gnome 1 est bas´e sur
                                      e                  e                                e
               e e                                e   `
une boucle d’´v´nements. Dans cette biblioth`que, a chaque bouton de l’interface graphique est
       e    e e                                                e                            e
associ´ un ´v´nement et des actions comme fermer une fenˆtre ou effacer un fichier peuvent ˆtre
        e `       e e
attach´es a ces ´v´nements.


1.2                e
             Le mod`le synchrone
                                                                   e     e   u
    La programmation synchrone [50, 9] se base sur un mod`le id´al o` les calculs et les com-
                          e           e                 e                   e
munications sont suppos´s instantan´s. Dans ce mod`le, le temps est d´fini logiquement comme
                    e        `                    e         e              e     `
une succession de r´actions a des signaux d’entr´e. La r´action du syst`me a son environnement
                 e            e                          e               e
est ainsi suppos´e instantan´e. Dans le cadre des syst`mes temps-r´el, cela signifie que le temps
    e               e                                     e                e `         e e
de r´action du syst`me est suffisamment rapide pour ˆtre toujours prˆt a traiter un ´v´nement
                                            e                                      e
venant de l’environnement. Pour les syst`mes interactifs cela signifie que l’unit´ de temps la
                                e              e                 e               e e
plus rapide est le temps de r´action du syst`me. Chaque r´action du syst`me d´finit alors un
instant.
                                            e                e
    Plusieurs familles de langages sont fond´es sur le mod`le synchrone. Signal [49], Lustre [51]
                                                               e
et Lucid Synchrone [30] sont des langages flots de donn´es. Ils manipulent des suites infinies
                                              e                                           e
de valeurs comme objets de base. Il existe ´galement des formalismes graphiques bas´s sur la
composition d’automates. Argos [70] en est un exemple. Enfin, un langage comme Esterel [12]
                                   e                                 e
a un style de programmation imp´ratif. Un comportement est d´fini par une succession d’actions
` e                                                 e         e e              e
a ex´cuter et plusieurs comportements peuvent ˆtre ex´cut´s en parall`le pour construire de
nouveaux comportements.
                                      e         `              e                      e e
    Dans ce document, nous nous int´ressons a l’approche r´active introduite par Fr´d´ric Bous-
                        e        e     e e                             e                      e
sinot [24]. L’approche r´active ´tant d´riv´e de Esterel, nous pr´sentons dans la suite le mod`le
synchrone sous cet angle.
     1
         http://www.gimp.org, http://www.gnome.org
                                             e
                                  1.2. Le mod`le synchrone                                        13




              e
    (a) Parall`le asynchrone.               e
                                  (b) Parall`le asynchrone (yield).              e
                                                                       (c) Parall`le synchrone.


                                                      e
        Fig. 1.1 – Comparaison des compositions parall`les synchrones et asynchrones.



1.2.1                        e
        La composition parall`le
                                     e                            e
    La notion d’instant permet de d´finir la composition parall`le synchrone de processus. Si e 1
       e                                 e                                e             e
et e2 d´signent deux expressions, la r´action de la composition parall`le e 1 ||e2 est d´finie par
    e                    e                           e                               e
la r´action de e1 et la r´action de e2 . Ainsi, par d´finition, e1 et e2 avancent au mˆme rythme.
                                e
    Reprenons l’exemple donn´ dans [98] qui compare la composition asynchrone des threads
                            e                                                           e
avec la composition parall`le des langages synchrones. Le but du programme est de d´crire un
                                                e
mouvement circulaire par composition parall`le de deux mouvement sinuso¨      ıdaux. Un processus
                                                      e
calcule l’abscisse du point et un autre son ordonn´e. En utilisant la syntaxe de Ocaml et en
                                  e                     e
notant || la composition parall`le, ce programme s’´crit :
  let alpha = ref 0.0 in                        let alpha = ref 0.0 in
  while (true) do                               while (true) do
    x := cos(!alpha);                 ||          y := sin(!alpha);
    alpha := !alpha +. 0.05;                      alpha := !alpha +. 0.05;
  done                                          done
                      e                                          e
Les deux processus d´clarent une variable locale alpha qui repr´sente un angle. Puis ils entrent
dans une boucle infinie. Le processus de gauche modifie l’abscisse du point en calculant la valeur
                                                                     e
du cosinus de alpha et augmente la valeur de l’angle alpha. De mˆme, le processus de droite
                  e           `          e
modifie l’ordonn´e du point a chaque it´ration de la boucle.
                          e                                                    e
    La figure 1.1(a) repr´sente les positions successives du point lorsque l’op´rateur || est im-
      e                                                                         e
plant´ avec les threads de la machine virtuelle de Ocaml. L’ordonnanceur ex´cute alternative-
                   e                                                               e
ment plusieurs it´rations du processus qui calcule l’abscisse du point puis il ex´cute plusieurs
  e                                    e                                         e
it´ration de celui qui calcule l’ordonn´e. Donc, une ligne horizontale est affich´e lorsque le pre-
                       e e                                                  e
mier processus est ex´cut´ et une ligne verticale lorsque l’ordonnanceur ex´cute le second.
                                                                              `         e
    Pour obtenir un cercle, il faut que l’ordonnanceur change de processus a chaque it´ration.
                                   `
Afin de donner des indications a l’ordonnanceur pour le changement de thread, la primitive
                e
yield est utilis´e :
  let alpha = ref 0.0 in                        let alpha = ref 0.0 in
  while (true) do                               while (true) do
    x := cos(!alpha);                 ||          y := sin(!alpha);
    alpha := !alpha +. 0.05;                      alpha := !alpha +. 0.05;
    Thread.yield();                               Thread.yield();
  done                                          done
14                                         1. Introduction

     e              e                                    e
Le r´sultat de l’ex´cution de ce programme est donn´ figure 1.1(b). Nous observons que le
      o               e     e
contrˆle change plus r´guli`rement entre les deux processus. Le mouvement est presque circu-
                              e                                      e `
laire. Mais ce n’est pas le r´sultat attendu. La primitive yield sugg`re a l’ordonnanceur de
changer de thread, mais ne garantit pas qu’il va le faire.
Remarque :
          e                     e e                                   e               `
   Si le mˆme programme est ex´cut´ en utilisant les threads du syst`me (linux 2.6.6) a la
                                                                    e
   place des threads de la machine virtuelle de Ocaml, il donne le r´sultat suivant :




                e                   e     e                                 e                e
     Les deux ex´cutions sont ici tr`s diff´rentes, illustrant ainsi le probl`me de portabilit´ des
     threads.
                       e               e                             e
    Maintenant si l’op´rateur || repr´sente la composition parall`le synchrone et si pause est
                              e             a
l’instruction qui suspend l’ex´cution jusqu’` l’instant suivant, les positions successives du point
                                     e e              e
lorsque le programme suivant est ex´cut´ sont donn´es figure 1.1(c).
  let alpha = ref 0.0 in                       let alpha = ref 0.0 in
  while (true) do                              while (true) do
    x := cos(!alpha);                 ||         y := sin(!alpha);
    alpha := !alpha +. 0.05;                     alpha := !alpha +. 0.05;
    pause;                                       pause;
  done                                         done
                                 `                                          e e          e
Ici, nous obtenons un cercle car a chaque instant les deux processus sont ex´cut´s. Par d´finition
                         e
de la composition parall`le synchrone, il ne peut pas y avoir un processus qui avance plus vite
                                                             e
que l’autre. Nous observons que l’ordonnancement est coop´ratif : chaque processus marque sa
fin d’instant.

1.2.2                                   e               e
         Les communications et les probl`mes de causalit´
    ´                                                                      e
    Etudions maintenant le mode de communication entre processus utilis´ dans le mod`le syn-e
                                                            e    e e
chrone. Les communications se font par diffusion instantan´e d’´v´nements. Les instants ´tant  e
       e           e e                    e
de dur´e nulle, un ´v´nement est soit pr´sent, soit absent pendant un instant, mais il ne peut
                                            e e         e           e
jamais avoir les deux statuts. De plus, les ´v´nements ´tant diffus´s, tous les processus en ont
une vision identique.
                 e                e                       ee
    Dans le mod`le synchrone, la v´rification de ces propri´t´s demande une analyse statique qui
                             e                                                   e
rejette les programmes incoh´rents. Cette analyse s’appelle l’analyse de causalit´ [13]. Illustrons
                                                             e
avec des programmes Esterel, quelques exemples de probl`mes de causalit´.     e
                                    e
    Le programme suivant est incoh´rent :
  signal s in
    present s then nothing else emit s end;
  end
                                              e
                                   1.2. Le mod`le synchrone                                      15

                                 e
La construction signal/in d´clare un nouveau signal s. Puis l’expression present teste si ce
              e                e                                                      e e
signal est pr´sent. S’il est pr´sent, l’instruction nothing qui ne calcule rien est ex´cut´e, sinon
                 e ee
le signal s est g´n´r´.
                                                                       e
    Dans ce programme, il n’existe pas de statut pour s qui soit coh´rent. Si nous supposons s
                                   e e                  e
absent, la branche else est ex´cut´e et donc s est ´mis. Dans ce cas, s est absent et pr´sent e
           e                                                 e
dans le mˆme instant. Nous supposons alors que s est pr´sent. Mais dans ce cas, la branche
             e e                     e             e              e         e
then est ex´cut´e et s n’est pas ´mis. Par cons´quent, l’hypoth`se “s pr´sent” est fausse. Dans
                                    e        e                                             e
cet exemple le signal s ne peut ˆtre ni pr´sent, ni absent, le programme est donc incoh´rent.
                              e          e                   e          e
    L’exemple suivant doit ˆtre rejet´ car les deux hypoth`ses “s pr´sent” et “s absent” sont
                                               e
possibles. Le comportement est donc non d´terministe :
  signal s in
    present s then emit s else nothing end;
  end
                                                                e       e           e
    Un programme n’est pas non plus causal lorsqu’un signal est ´mis apr`s que sa pr´sence ait
ee      e
´t´ test´e :
  signal s in
    present s then emit t else nothing end;
    emit s;
  end
       e               e                   e      e                e                   e     e
Ici, l’´mission de t d´pend de s qui est ´mis apr`s son test de pr´sence durant la mˆme r´action.
                                         e                                    e                e
     Il n’y a pas seulement le test de pr´sence qui peut introduire des probl`mes de causalit´. Par
                                                  e
exemple, la construction abort/when est probl´matique. C’est une construction de pr´emptione
                           e                         e                  u              e
forte. Elle interrompt l’ex´cution de son corps au d´but de l’instant o` le signal est ´mis (premier
                         e                                       `        e
instant exclu). La pr´emption est dite forte par opposition a la pr´emption faible qui laisse
   e                                            e
ex´cuter son corps pendant l’instant de la pr´emption.
  signal s in
    abort
      pause;
      emit s
    when s;
  end
              e                           e                                       e e
Ici, au deuxi`me instant, si s est suppos´ absent, le corps du abort/when est ex´cut´. Donc s
     e                              e                                     e e
est ´mis ce qui contredit l’hypoth`se d’absence de s. Si s est suppos´ pr´sent, le corps du
                           e e                         e                              e
abort/when n’est pas ex´cut´ et donc s n’est pas ´mis. Ceci contredit l’hypoth`se “s est
   e                                    e
pr´sent”. Donc le programme est incoh´rent.
          e                                   e                                     e
     La pr´emption faible weak/abort/when ex´cute son corps avant d’effectuer la pr´emption et
     e                        e                                           e                 e
d’ex´cuter le traitement de l’´chappement. Dans l’exemple suivant, il y a ´galement un probl`me
            e   e                      e           e                                    e
de causalit´. L’´mission du signal s2 d´pend de l’´mission du signal s1 qui est effectu´e apr`se
      e
la pr´emption :
  signal s1, s2, k in
    weak abort
      await s1;
      emit s2
    when k do emit s1; end weak abort;
  end
16                                        1. Introduction

                                                   e
    Les signaux transportant des valeurs peuvent ´galement introduire des boucles de causalit´.  e
                                                                        e
Dans l’exemple suivant, le signal s transporte la somme des valeurs ´mises pendant l’instant.
                e                                   e   e
La valeur 1 est ´mise sur ce signal. La variable x r´cup`re la valeur du signal. Puis, la valeur de
      e                    e
x est ´mise sur s. Donc s ´met sa propre valeur.
  signal s := 0 : combine integer with + in
    emit s(1);
    var x := ?s: integer in
      emit s(x)
    end
  end
                       ıtre                     e
Nous voyons ici apparaˆ une boucle de causalit´ car si x vaut 1 alors l’instruction emit s(x)
e
´met 1 et donc x vaut 2 !
                                                    e
    Il faut enfin remarquer que la composition parall`le de deux programmes qui sont causaux
            e
n’est pas n´cessairement causale.
  signal s1, s2 in
    present s1 then emit s2 else nothing end
    ||
    present s2 then nothing else emit s1 end
  end
                                                                                  e
Ici, chaque present pris individuellement est causal, mais leur composition parall`le introduit
          e
une incoh´rence.


1.3           e    e           e e
        Le mod`le r´actif de Fr´d´ric Boussinot
             e e                 ee                   e e                   e             e
    Le mod`le r´actif [18, 92] a ´t´ introduit par Fr´d´ric Boussinot au d´but des ann´es 1990.
                                                                    e
Le langage ReactiveC [16], une extension de C proposant un op´rateur merge de composition
       e                   e                         e e                e`
parall`le, en est la premi`re implantation. Le mod`le r´actif est adapt´ a la programmation de
     e                              e              u                                        e e
syst`mes interactifs, plus particuli`rement ceux o` un grand nombre de processus sont ex´cut´s
           e      u
en parall`le et o` les processus communiquent et sont fortement synchronis´s.   e
         e                        e                                 e e
    L’id´e de la programmation r´active est d’utiliser un langage g´n´raliste pour la programma-
                                        e                `                    e
tion des parties algorithmiques du syst`me et d’ajouter a ce langage un mod`le de la concurrence
                   e                                  e
qui soit simple, d´terministe et modulaire. Ce mod`le de la concurrence doit pouvoir se marier
                                      e e
harmonieusement avec un langage g´n´raliste.
                         e e                                 e
    Le principe du mod`le r´actif est de reprendre le mod`le de concurrence des langages syn-
                                    e                e          `                 `
chrones et de supprimer les probl`mes de causalit´ qui sont a la fois : durs a comprendre, un
           `             e             `                                              e e
obstacle a la modularit´ et difficiles a analyser dans le contexte d’un langage g´n´raliste. La
       e                            e    ee
premi`re formalisation de ce mod`le a ´t´ faite dans SL [24].
             e                                                  e                   e
    Nous pr´sentons maintenant deux visions de l’approche r´active. La premi`re est un affai-
                                                                   e                  e
blissement de l’approche synchrone afin de supprimer les probl`mes de causalit´. La seconde
  e          e
d´taille l’ex´cution d’un instant pour donner une vision constructive du mod`le.  e

1.3.1                          e
         Ajout de retard au mod`le synchrone
                                               e              e e e                        e
   Nous allons reprendre les exemples de probl`mes de causalit´ pr´c´dents avec une interpr´tation
 e                                                     e                e
r´active et voir comment l’insertion d’un retard peut r´soudre ces probl`mes.
                                   e e              e e
                        1.3. Le mod`le r´actif de Fr´d´ric Boussinot                            17

             e          e                e   e                                       e
    La premi`re caract´ristique du mod`le r´actif est d’ajouter un retard pour la r´action a  `
l’absence d’un signal. Donc dans la construction present/then/else, si le signal est absent, la
                    e e `
branche else est ex´cut´e a l’instant suivant.
                                                      e
    Reprenons le premier exemple de programme incoh´rent. Nous ajoutons ici une apostrophe
                                        e
aux constructions de Esterel dont la s´mantique change :
  signal s in
    present’ s then nothing else emit s end;
  end
           e                                     `                                e
Si l’hypoth`se que s est absent est faite, alors a l’instant suivant le programme ´mettra s. Ceci
                          e        e
ne contredit pas l’hypoth`se que s ´tait absent au premier instant. Ce programme devient donc
causal. Autrement dit ce programme correspond au programme Esterel suivant :
  signal s in
    present s then nothing else pause; emit s end;
  end
                       e                e                      e             e
    La seconde caract´ristique du mod`le est de toujours privil´gier l’hypoth`se d’absence d’un
                                      u                e         e
signal. Ainsi, sur l’exemple suivant o` les deux hypoth`ses s pr´sent et absent sont possibles,
         e
l’hypoth`se s absent est prioritaire.
  signal s in
    present’ s then emit s else nothing end;
  end
    e                      e
La r´action devient alors d´terministe.
                                       e
   La combinaison de ces deux caract´ristiques rend causal l’exemple suivant :
  signal s in
    present’ s then emit t else nothing end;
    emit s;
  end
                `                                                        e e `
Contrairement a Esterel, si s est absent, la branche else est ex´cut´e a l’instant suivant ;
  e                               e e                                                           e
l’´mission du signal s est donc d´cal´e d’un instant. Ainsi, dans cet exemple, les deux hypoth`ses
     e
“s pr´sent” et “s absent” sont possibles. C’est donc le choix s absent qui est fait.
                 e e             e                                                      e
    Dans le mod`le r´actif, la pr´emption forte est interdite. De plus, le traitement d’´chappement
         e                         e`                        e                    e
d’une pr´emption faible est report´ a l’instant suivant la pr´emption. Par cons´quent, la construc-
                                                  e                  e                e
tion abort/when n’existe pas dans l’approche r´active et le probl`me de causalit´ de l’exemple
                                   e                           e                           e
du weak/abort/when est supprim´ car le signal s1 n’est pas ´mis dans l’instant de la pr´emption,
                  `
mais uniquement a l’instant d’apr`s.e
  signal s1, s2, k in
    weak abort’
      await s1;
      emit s2
    when k do
      emit s1;
    end weak abort;
  end
                                                     u                    e
Cet exemple correspond au programme Esterel suivant o` une pause est ajout´e lors du
                e
traitement de l’´chappement :
18                                      1. Introduction

  signal s1, s2, k in
    weak abort
      await s1;
      emit s2
    when k do
      pause;
      emit s1;
    end weak abort;
  end
             e        e                 e   e                                      e   e
    La derni`re caract´ristique du mod`le r´actif est d’ajouter un retard pour la r´cup´ration
                                                                                     e e
de la valeur d’un signal. Donc dans l’exemple suivant, l’instruction emit s(x) est ex´cut´e au
      e                                       ea e
deuxi`me instant lorsque la valeur de x est d´j` fix´e.
  signal s := 0 : combine integer with + in
    emit s(1);
    var x := ?’s: integer in
      emit s(x)
    end
  end
Ainsi, cet exemple correspond au programme Esterel suivant :
  signal s := 0 : combine integer with + in
    emit s(1);
    var x := ?s: integer in
      pause;
      emit s(x)
    end
  end
                        e
   Enfin, dans ce mod`le, comme tous les programmes sont causaux, la composition de deux
                                                                             e    u
programmes causaux reste un programme causal. Sur l’exemple suivant, l’hypoth`se o` s1 et
s2 sont absents est valide.
  signal s1, s2 in
    present’ s1 then emit s2 else nothing end
    ||
    present’ s2 then nothing else emit s1 end
  end
                                                        e e `
En effet dans ce cas, les deux branches else sont ex´cut´es a l’instant suivant le test. Donc
  e                                         e                   e e
l’´mission de s1 ne contredit pas les hypoth`ses de l’instant pr´c´dent.

1.3.2                   e
        Absence d’hypoth`se sur les signaux
                             e     e          e     e            e           e
    Une autre vision du mod`le r´actif est pr´sent´e ici. Les mˆmes caract´ristiques qu’avec
                              e                  e           e
l’ajout de retards dans le mod`le synchrone vont ˆtre retrouv´es.
                                      e           e
    Avec cette approche, toute hypoth`se sur la pr´sence ou l’absence des signaux est interdite
       e                                                                       e
et la r´action d’un instant est construite comme une succession de micro-r´actions jusqu’`    a
l’obtention d’un point fixe.
                                            ´
                                       1.4. Etat de l’art                                        19

          e                                                                ee             e
    Au d´but d’un instant tous les signaux ont un statut qui est consid´r´ comme ind´termin´.      e
                  e                           e                             e` e
Au cours de la r´action, lorsqu’un signal est ´mis, son statut est alors fix´ a pr´sent. Le test d’un
                              e       e             e     e                           e
signal dont le statut est ind´termin´ ne peut pas ˆtre r´solu. Le composant parall`le effectuant
                                                                   e               e
le test est alors suspendu. Lorsque tous les composants du syst`me ont termin´ leur ex´cutione
                                                                    e       e
ou sont suspendus sur le test de signaux dont le statut est ind´termin´, alors la fin d’instant
      e    e `                                                   e
est d´clar´e. A partir de ce moment, il ne peut plus y avoir d’´mission de signaux donc tous les
                        eee
signaux qui n’ont pas ´t´ ´mis sont absents.
                             e              e                         e
    Il y a alors une seconde ´tape dans la r´action qui s’appelle la r´action de fin d’instant. Dans
       e                                          e                                     e      e
cette ´tape le statut de tous les signaux est fix´, les tests d’absence peuvent donc ˆtre r´solus
        e                           e      e e
et la r´action de l’instant suivant ˆtre pr´par´e.
                                                                               e
    Nous voyons maintenant intuitivement la justifications des cinq caract´ristiques du mod`le     e
 e
r´actif :
                                   e                e `
    – Il ne peut pas y avoir de r´action instantan´e a l’absence d’un signal car c’est seulement
      `                                                e      e                              `
      a la fin d’instant, que le statut d’absence peut ˆtre fix´. Sinon cela correspondrait a faire
                      e                          e                      e
      une hypoth`se sur l’absence qui pourrait ˆtre contredite par l’´mission du signal.
                   e                               e e                                           ee
    – L’hypoth`se d’absence d’un signal est privil´gi´e par le fait que les signaux sont consid´r´s
          e                                    e
      pr´sents seulement une fois qu’ils sont ´mis. De plus, le test d’un signal dont le statut est
           e         e          e                                             e
      ind´termin´ suspend l’ex´cution ce qui ne peut jamais engendrer d’´mission de signaux.
               e                 e            `
    – La pr´emption forte est ´quivalente a faire un test d’absence d’un signal car le corps
                                               e e             e
      de la construction abort/when est ex´cut´ instantan´ment uniquement si le signal de
          e                                                       e                  e `
      pr´emption est absent. Comme il ne peut pas y avoir de r´action instantan´e a l’absence,
             e
      la pr´emption forte est interdite.
                      e          e                                    e
    – Il y a un d´lai avant l’ex´cution de la continuation d’une pr´emption faible car le corps
              e                                                                 e
      peut ˆtre suspendu sur l’attente d’un signal dont le statut sera fix´ seulement a la fin`
      d’instant.
                                              e    e                                 e     u
    – Il faut attendre la fin d’instant pour r´cup´rer la valeur d’un signal afin d’ˆtre sˆr de ne
                                          e
      pas manquer une valeur qui serait ´mise plus tard dans l’instant.
              e     e                                             e               e
    Le mod`le r´actif fournit toujours un ordonnancement coh´rent et sans ´chec. En contre-
                                 e                e      ıne
partie, la suppression des probl`mes de causalit´ entraˆ une diminution de l’expressivit´ par  e
                    e                             e                  e `
rapport au mod`le synchrone. Par exemple, la r´action instantan´e a l’absence d’un signal de-
                                            e                         e
vient impossible. Ainsi, il y a une dissym´trie entre le test de pr´sence et celui de l’absence.
                 e                                        `
Cette dissym´trie peut rendre les programmes difficiles a comprendre.


1.4     ´
        Etat de l’art
1.4.1            e                              e
          Les diff´rents travaux sur l’approche r´active
           e                                          ee e e                             e
   Nous pr´sentons ici les principaux travaux qui ont ´t´ r´alis´s autour de l’approche r´active.
                                            e
Nous reviendrons au chapitre 10 sur les diff´rences avec notre proposition.

Esterel
      e                                                     e
    Mˆme si Esterel [12, 13, 11] n’est pas un langage r´actif (au sens de F. Boussinot), il a sa
                                  `                               e
place dans cette liste car il est a l’origine des travaux sur le r´actif.
                                                  e`                        e
    Esterel est un langage synchrone destin´ a la programmation de syst`mes temps-r´el et e
                                                  e `      e e
de circuits. Il dispose de compilateurs destin´s a la g´n´ration de logiciel [32, 89, 38] ou de
circuits [45, 11].
20                                         1. Introduction

            e e
    Le mod`le r´actif reprend de Esterel la vision du temps en instants logiques, la composi-
           e                                                         e
tion parall`le synchrone et la communication par diffusion instantan´e. De plus, la plupart des
                    e              e e
constructions utilis´es dans le mod`le r´actif sont issues de Esterel.

ReactiveC

                                     e                          e e                   e e
    ReactiveC [16, 18] est la premi`re implantation du mod`le r´actif faite par Fr´d´ric Bous-
                                                       e         e                          e
sinot. C’est une extension du langage C avec des proc´dures r´actives (rproc). Ces proc´dures
                                                                           e
sont des fonctions C qui ont un comportement temporel. Dans ces proc´dures, des instructions
 e                 e         e                                                       e           `
r´actives peuvent ˆtre utilis´es. Parmi ces instructions, il y a l’instruction stop (´quivalente a
                                           e                                e              e
pause) qui marque la fin d’instant et l’op´rateur de composition parall`le merge. L’ex´cution
           e                                                  e
d’une proc´dure se fait instant par instant en utilisant l’op´rateur d’application react.
             e       e               e
    Les proc´dures r´actives peuvent ˆtre d´finies r´cursivement. La r´cursion n’´tant pas limit´e
                                           e       e                    e         e             e
`      e                                      e                                      e
a la r´cursion terminale, cela permet de cr´er dynamiquement des processus r´actifs. Dans
                          e                          `                        e
l’exemple suivant, la proc´dure Split se duplique a chaque instant (l’op´rateur exec ex´cute  e
         e      e
une proc´dure r´active) :
  rproc void Split(){
    stop;
    merge
      exec Split();
      exec Split();
  }
                                                              u
    ReactiveC propose des constructions de bas niveau o` les communications se font par
  e             e                                      e e            e
m´moire partag´e. Il n’y a pas de communication par ´v´nements d´finie dans le langage.
                         e
    Une des particularit´s de ce langage est de proposer des instructions qui permettent de
     o                       `    e                                                    o     e
contrˆler l’ordonnancement a l’int´rieur d’un instant. Ainsi, le programmeur a un contrˆle tr`s
          e
fin de l’ex´cution du programme.
                  ee       e                                                            e
    Ce langage a ´t´ utilis´ comme noyau pour l’implantation de plusieurs formalismes r´actifs
             e                   e
comme les r´seaux de processus r´actifs [17], SL [24] ou les Reactive Scripts [25].

SL

                            e               e
    SL [24, 18] a formalis´ l’approche r´active en proposant une variante de Esterel sans
      e                e                                     e
probl`mes de causalit´. Dans ce langage aucune hypoth`se sur les signaux n’est autoris´e : un  e
              e                     eee             e            `             e e
signal est pr´sent une fois qu’il a ´t´ ´mis, et il ´tait absent a l’instant pr´c´dent si personne ne
        e
l’avait ´mis.
    `                   e                          e             e              e        e
    A partir de cette d´finition intuitive, une s´mantique op´rationnelle d´crit la r´action d’un
                                           e                                                e
instant comme une succession de micro-r´actions construisant l’ensemble des signaux ´mis pen-
                       e             e                 e
dant l’instant. Cette s´mantique d´crit le noyau r´actif du langage sans prendre en compte les
              e
signaux valu´s.

Junior et les SugarCubes

                                                               e
    Junior [57, 56] et les SugarCubes [26] sont deux biblioth`ques pour la programmation
 e
r´active en Java. Junior est une proposition de Laurent Hazard, Jean-Ferdinand Susini et
   e e                                         e        `         `
Fr´d´ric Boussinot sur le noyau de primitives r´actives a ajouter a Java. Les SugarCubes
                                           ´
                                      1.4. Etat de l’art                                      21

                      e      e
sont principalement d´velopp´s par Jean-Ferdinand Susini et proposent une interface plus riche
                                         e
que celle de Junior. Ainsi, Junior peut ˆtre vu comme le noyau des SugarCubes.
                      e                              e                   e
    Ces langages se pr´sentant sous forme de biblioth`ques Java, il faut ´crire ainsi les parties
 e
r´actives en syntaxe abstraite. Par exemple, le programme Junior qui affiche les num´ros      e
            e
d’instant s’´crit :
  import junior.*;
  import jre.*;

  public class Example {
    static int cpt = 0;

      public static void main(String[] args) {
          Program P =
              Jre.Loop
                (Jre.Seq
                   (Jre.Atom(new Action(){
                          public void execute(Environment env){
                              cpt++;
                              System.out.println("Instant "+cpt);
                          }}),
                    Jre.Stop()));

          Machine M = Jre.Machine();
          M.add(P);
          for(int i=1; i<=10; i++) {
              M.react();
          }
      }
  }
         e              ee                         e
    La s´mantique de r´f´rence de Junior est donn´e par Rewrite [56] et par son implantation
directe. De nombreuses autres implantations existent. La plus efficace est Simple [55] mais
                        e                  `
elle n’est pas formalis´e et contrairement a ce que son nom pourrait laisser croire, elle repose
sur une implantation complexe. Parmi les autres implantations nous pouvons citer Replace,
                                                              e e
Storm [100], Reflex [28] et l’implantation que nous avons r´alis´e Glouton [66].
                               e
    Il faut noter qu’il existe ´galement des implantations de Junior dans d’autres langages :
Senior [35] en Scheme et Jrc [83] en C.

Rejo
                                                 e            e          e
    Rejo [1] est une extension de Java avec la d´finition de m´thodes r´actives. Ce langage
                                     e
produit du Java utilisant la biblioth`que Junior. Un des premiers objectifs de ce langage est
                                                                               e e       e
de fournir une syntaxe simple pour la programmation Junior. Ainsi, l’exemple pr´c´dent s’´crit
                 c
en Rejo de la fa¸on suivante :
  import junior.*;
  import ros.kernel.*;
22                                       1. Introduction

  public class Example {
    static int cpt = 0;

      public reactive rmain(String[] args) {
          loop{
              cpt++;
              System.out.println("Instant "+cpt);
              stop;
          }
      }

      public static void main(String[] args) {
          Machine M = Jr.Machine();
          M.add(new Example.rmain(args));
          for(int i=1; i<=10; i++) {
              M.react();
          }
      }
  }

                  e                                                       e
   Rejo permet ´galement de programmer des agents mobiles. Un objet r´actif implante le com-
                                      `            e                                     e
portement d’un agent qui peut migrer a travers le r´seau en utilisant la plate-forme d’ex´cution
       e      e         u
Ros d´velopp´e par Ra´l Acosta-Bermejo.
                            e
   Il existe une version exp´rimentale de Rejo en C qui s’appelle Raul.


Les Icobjs

                          e
   Les Icobjs [15, 28] d´finissent un langage graphique pour la programmation de syst`mese
 e                                                                       e               e
r´actifs. Des objets graphiques (icobjs) implantant des comportements r´actifs peuvent ˆtre
        e
compos´s afin de construire de nouveaux icobjs.
                                         `
   Le but de ce langage est de proposer a des non-informaticiens un environnement graphique
                                                       `                                   e
permettant de construire des comportements complexes a partir d’icobjs primitifs (programm´s
                                                       e e `         e                e
en Junior). Il existe par exemple un environnement d´di´ a la mod´lisation de syst`mes en
physique [95].
             e                     e     e      e
   La premi`re version des Icobjs ´tait d´velopp´e en ReactiveC et Tcl-Tk [81]. Les versions
      e
plus r´centes se basent sur Junior.


Loft et FairThreads

                                                             e                    e
    Les Fair Threads [21, 97, 19] proposent une biblioth`que de threads coop´ratifs bas´s   e
            e    e           e     e                    e                           e
sur le mod`le r´actif. La sp´cificit´ de cette biblioth`que est qu’elle permet de m´langer de
                         e         e
l’ordonnancement coop´ratif et pr´emptif. Plusieurs ordonnanceurs synchrones peuvent ˆtre e
   e e               e
ex´cut´s en parall`le. La composition de ces ordonnanceurs est asynchrone.
                   e                 e       e e
    Dans ce mod`le, un thread peut ˆtre ex´cut´ dans une zone synchrone avec un ordonnan-
              e          e   e                                       e e       c
cement coop´ratif ou d´tach´ de tout ordonnanceur synchrone et ex´cut´ de fa¸on asynchrone
avec le reste de l’environnement. De plus, les threads peuvent changer d’ordonnanceur en cours
     e
d’ex´cution et passer du mode synchrone au mode asynchrone.
                                          ´
                                     1.4. Etat de l’art                                      23

    Des implantations de Fair Threads sont disponibles en Scheme, Java et C. En Ocaml,
           e                                                              e            e
la biblioth`que HirondML [104] est une version des Fair Threads int´grant de la mobilit´.
    Loft [20] propose un langage au-dessus des Fair Threads. C’est une extension de C qui
                                       e
comme Rejo pour Junior, facilite le d´veloppement d’applications en Fair Threads. Par
                                                               ee e e
exemple, une implantation des automates cellulaires [22, 23] a ´t´ r´alis´e en Loft.

Reactive Programming in Standard ML
             e       e             e                                e
    La premi`re exp´rience d’int´gration de la programmation r´active dans des langages fonc-
           ee
tionnels a ´t´ faite en Standard ML [76] par Riccardo Pucella [91]. Par la suite, il y a eu
                                  e    e
d’autres implantations du mod`le r´actif dans cette famille de langages comme Senior [35],
Fair Threads [97], . . .
                           e             e
    Dans [91], l’auteur pr´sente une s´mantique des constructions de ReactiveC dans un lan-
                           e          e
gage ML. La particularit´ de cette s´mantique est de prendre en compte l’ensemble du langage.
       e      `                                               e
Elle pr´sente a la fois la partie fonctionnelle et la partie r´active.
                                         e                             e
    De ce travail est issu une biblioth`que pour la programmation r´active qui fait partie de la
distribution de Standard ML of New Jersey [99].

ULM
                                                        c
    ULM [14, 40] est une extension de Scheme con¸u pour la programmation de syst`mes       e
         e u
distribu´s o` les processus sont mobiles. ULM s’inspire de Fair Threads auquel il ajoute des
                 e e `
constructions d´di´es a la mobilit´.e
                         e
    ULM suit le mod`le des GALS (Globally Asynchronous Locally Synchronous) o` chaque  u
                e      e       e               u
site est un syst`me r´actif d´terministe et o` les communications entre sites sont asynchrones.
                             e          e                     ee                e
    Une attention particuli`re est port´e au traitement des r´f´rences dans la s´mantique. Dans
                                                      e
le cadre de processus mobiles, la localisation de la m´moire est une question fondamentale pour
    u e                                                              e e           e
la sˆret´ de fonctionnement. En particulier, si deux processus ex´cut´s en parall`le partagent
         e                                                            e
de la m´moire et si un des deux processus migre, il faut pouvoir sp´cifier le comportement des
                                        e    `      e
processus lorsqu’ils vont essayer d’acc´der a la m´moire.
                             e e                                                e
    Il existe une version all´g´e de ULM en C. Cette version (Lurc [64]) se pr´sente sous forme
            e                                `                          e
de biblioth`que proposant une alternative a l’utilisation de la biblioth`que des PThreads [44].

SL Revisited
                  e               e                  e      `                   e
   Des travaux r´cents [3, 2] d´finissent un noyau r´actif a base de threads coop´ratifs. Ce
                              e                                           e
noyau est proche du cœur r´actif de ULM ou des Fair Threads. Ce mod`le est utilis´ en  e
                              e                          e
particulier pour formaliser l’´quivalence de programmes r´actifs.

1.4.2                                                  e     e
        Autres approches pour la programmation des syst`mes r´actifs
         e                                                                        e
   Nous ´tudions maintenant d’autres langages pour la programmation de syst`mes r´actifs.e
                       `e                                                      e
Nous ne cherchons pas a ˆtre exhaustifs et nous portons une attention particuli`re aux langages
fonctionnels car notre proposition est une extension de ML.

                     e
Langages flots de donn´es
                                                          e              `
   Lucid Synchrone [30, 90] est un langage flots de donn´es synchrone a la ML. Ce lan-
                                                                  e
gage est une extension de Lustre avec des traits de ML comme l’inf´rence de type et l’ordre
24                                                  1. Introduction

    e                                                              e        e
sup´rieur. Contrairement aux langages synchrones classiques, la d´finition r´cursive de processus
              e                              e
et donc la cr´ation dynamique sont autoris´es dans Lucid Synchrone.
                  `               e                               e e
    Par rapport a l’approche r´active qui part d’un langage g´n´raliste pour lui ajouter des
                                                                        `
constructions synchrones, Lucid Synchrone fait le chemin inverse : a la base c’est un langage
            `                      e                                            e e
synchrone a la Lustre qui est ´tendu avec des traits venant des langages g´n´ralistes. Ainsi,
                              e                e e
il n’a pas toute l’expressivit´ d’un langage g´n´raliste. Mais en contrepartie, l’ordonnancement
                     e
des processus parall`les est fait statiquement.
   Fran [39] (Functional Reactive ANimation) et Frp [105] (Functional Reactive
                                                                  e
Programming) sont deux autres exemples de langages flots de donn´es avec des aspects dyna-
                           e                             e                                  e
miques. Ces langages se pr´sentent sous forme de biblioth`ques Haskell [85]. La particularit´
                                       e
de ces langages est de proposer un mod`le continu du temps.
                              e          e e`                        e
     Mgs [33] est un langage d´claratif d´di´ a la simulation de syst`mes dynamiques en particu-
lier dans le domaine de la biologie. Le langage repose sur la notion de collections topologiques 2
                                                                                         e
et de transformations sur ces collections. Ce langage n’est pas purement flots de donn´es, mais
                      e
les simulations se pr´sentent souvent comme des flots de collections.


Mondes virtuels

                                                    e
    Les mondes virtuels sont des exemples de syst`mes interactifs. Dans ce domaine, des lan-
      `                     e       e                                                    e
gages a base d’agents sont d´velopp´s. Ces langages doivent en particulier permettre l’ex´cution
                                                                          `
concurrente de plusieurs agents. Il proposent ainsi une autre alternative a la programmation de
    e
syst`mes interactifs.
    Parmi ces langages, nous pouvons par exemple citer oRis [54] et InViWo [94]. La parti-
       e
cularit´ de l’atelier InViWo est de proposer le langage de programmation Marvin qui a une
syntaxe proche de Esterel. Dans ce langage, un agent est un programme synchrone, mais la
composition entre agents est asynchrone.


Calculs de processus

   Les calculs de processus comme CCS/SCCS [74] ou le π-calcul [75] ont pour but de
                                                                         e
construire un noyau minimal pour exprimer la concurrence. Mais il existe ´galement des im-
                                                                   `
plantations de ces calculs. Par exemple JoCaml [43] est un langage a la ML proposant des
                               e
constructions concurrentes bas´es sur le join-calcul [42].


Langages fonctionnels concurrents

    ConcurrentML [93] est une extension de Standard ML avec de la programmation
                                       e            e                       e
concurrente. ConcurrentML est bas´ sur le mod`le des threads et privil´gie la communi-
                            e                            e                e
cation par messages. Le mod`le de communication propos´ par le langage s´pare la description
        e                           e         e
des op´rations de synchronisation (´mission, r´ception de message) de la synchronisation elle
  e                                                          e
mˆme. Cette approche permet de combiner simplement les op´rations faites lors des communi-
cations.
    Il existe de nombreux autres langages fonctionnels pour la concurrences comme Concur-
rent Haskell [86] ou Erlang [5].
     2
                                                      ee
         Une collection topologique est un ensemble d’´l´ments avec une relation de voisinage.
                                        1.5. ReactiveML                                           25

1.5     ReactiveML
1.5.1    Les traits du langage
                    e                        e
   Ce document d´crit la conception, la s´mantique et l’implantation de ReactiveML, un
                                  e           e e        `
langage de programmation int´grant le mod`le r´actif a Ocaml.
   – ReactiveML est une extension de Ocaml. Il reprend de Ocaml sa syntaxe et sa
      e                             o             e                          e            e
     s´mantique. Ce langage hˆte permet de d´finir les structures de donn´es et les op´rations
                                                  `
     pour les manipuler. ReactiveML ajoute a ce langage une notion de temps logique discret
                                                    e
     global et des constructions permettant de d´crire des comportements temporels.
                                                                                e
   – ReactiveML conserve des traits de ML comme le typage et l’ordre sup´rieur. Le langage
                         e                   ee                              e
     est fortement typ´ et les types sont inf´r´s par le compilateur. Le syst`me de type est une
                         e
     extension du syst`me de type de Ocaml de sorte que les programmes Ocaml existant
                   e
     gardent le mˆme type.
          e                                    e              e
   – La s´mantique du langage est formalis´e avec une s´mantique comportementale et une
      e              e                 e                                         e   e
     s´mantique op´rationnelle. La s´mantique comportementale est la premi`re s´mantique a        `
                          e              e e            e            e                `
     grands pas propos´e pour le mod`le r´actif. La s´mantique op´rationnelle est a petits pas
                                            e`                              ee                u e
     offrant ainsi un formalisme plus adapt´ a la preuve de certaines propri´t´s comme la sˆret´
                               e                                 e                 e
     du typage. Ces deux s´mantiques ont pour particularit´ par rapport aux s´mantiques de
                                                e     e                  a     `
     Junior ou SL de prendre en compte l’int´gralit´ du langage, c’est-`-dire a la fois les parties
      e
     r´actives et les parties algorithmiques. Cet aspect permet de clarifier les interactions entre
     ces deux niveaux du langage.
   – Les programmes ReactiveML sont traduits dans des programmes Ocaml s´quentiels      e
                             e                            e
     (sans threads). L’op´ration de composition parall`le est une composition logique. Elle ne
                       `         e          e                          e    e
     correspond pas a une ex´cution parall`le. Nous n’avons pas trait´ l’ex´cution sur machines
            e                                                   e    e e
     parall`les. En contrepartie, les programmes peuvent ˆtre ex´cut´s sur des syst`mes nee
     proposant pas de threads.
   – Contrairement aux langages synchrones classiques, l’ordonnancement des calculs est fait a    `
         e                 `                                e
     l’ex´cution et non a la compilation. Cependant l’ex´cution de programmes ReactiveML
     repose sur l’utilisation de techniques d’ordonnancement efficaces permettant d’ex´cuter   e
     un grand nombre de processus concurrents.

1.5.2    L’approche suivie dans ReactiveML
                                             e   e           ee e e
    De nombreuses implantations du mod`le r´actif ont ´t´ r´alis´es. Parmi elles, un nombre
                                                                        e e
important sont des librairies dans des langages de programmation g´n´ralistes. Cette approche
          e                             e `                     e             o                 e e
semble tr`s attirante car elle donne acc`s a toute l’expressivit´ du langage hˆte et est assez l´g`re
`                      e                              `
a mettre en œuvre. N´anmoins, elle peut conduire a des confusions entre les valeurs du langage
  o                         e
hˆte et les constructions r´actives. De plus avec cette approche, il est difficile d’introduire des
                               e
techniques de compilation sp´cifiques, des optimisations et des analyses de programmes.
    L’approche que nous avons choisie est de proposer la concurrence au niveau du langage.
Nous enrichissons donc un langage ML strict avec de nouvelles primitives de programmation
 e                                                                 e
r´active. Un programme ReactiveML est un ensemble de d´finitions de valeurs ML et de
         e                                                                         e
valeurs r´actives que nous appelons des processus. Les processus sont compos´s d’expressions
                          e
ML et de constructions r´actives. En comparaison avec l’approche sous forme de librairies, nous
                                               u              `
pensons que l’approche “langage” est plus sˆre et conduit a une programmation plus naturelle.
                                                                                  e e
    ReactiveML est construit au dessus de Ocaml car c’est un langage g´n´raliste qui est
`                                          e
a la fois expressif, efficace et dont la s´mantique est simple. Ce dernier point nous permet
26                                        1. Introduction

de formaliser l’ensemble de ReactiveML et ainsi de clarifier les communications entre les
          e                                                                 e          e
parties r´actives et algorithmiques du langage. C’est une des originalit´s de nos s´mantiques de
                                     e                                                      e
prendre en compte les signaux valu´s. Cela permet par exemple de rendre explicite le ph´nom`ne  e
   e                     e
d’´chappement de port´e des signaux.
                                                    `                      e e
     Pour proposer une alternative aux threads ou a la programmation ´v´nementielle, la rapidit´  e
     e                                                 e
d’ex´cution est une question importante. L’efficacit´ de ReactiveML est due au langage hˆte       o
       e                   e                                             e
mais ´galement aux strat´gies d’ordonnancement des programmes r´actifs. Les deux techniques
                                   e
d’ordonnancement que nous pr´sentons dans ce document s’inspirent des travaux de Laurent
                                  e
Hazard. L’implantation est bas´e sur l’utilisation de files d’attentes de sorte qu’une expression
          e                                            e          e
est activ´e uniquement lorsque le signal dont elle d´pend est ´mis.
                                                 e     ee      e `       e
     Pour l’implantation, une attention particuli`re a ´t´ port´e a l’int´gration au langage Ocaml.
                                                        e                                   `
D’une part, pour l’implantation des constructions r´actives nous avons fait attention a ce que
l’implantation soit efficace et puisse utiliser directement le glaneur de cellules (GC) de Ocaml.
                                                      e e
D’autre part pour les expression ML, nous avons r´alis´ une analyse statique permettant de les
                                        e
identifier et donc de les laisser inchang´es par le compilateur ReactiveML. Ainsi, elles peuvent
e        e e               u              `           e
ˆtre ex´cut´es sans surcoˆt par rapport a du code ´crit directement en Ocaml.


1.6                  e
        Plan de la th`se
                         e                                   e       e           e     e
    Le document se d´compose en cinq parties. La premi`re pr´sente le mod`le r´actif et le
langage ReactiveML avec un tutoriel au chapitre 2.
                                 e                                      e   e
    Dans la seconde partie, la s´mantique formelle du langage est pr´sent´e. Cette partie com-
                                      e                              `
mence au chapitre 3 par donner une s´mantique comportementale a grands pas au langage. Dans
        e                   e                  `    e              e
cette s´mantique chaque r´action correspond a l’ex´cution compl`te d’un instant et permet ainsi
                                     `     e                               e
de s’abstraire de l’ordonnancement a l’int´rieur de l’instant. Puis nous pr´sentons au chapitre 4
      e               e          `                           `    e
une s´mantique op´rationnelle a petits pas. Contrairement a la s´mantique comportementale, la
 e               e             e
s´mantique op´rationnelle d´crit la construction d’un instant comme une succession de micro-
 e                         e                         e                                  e
r´actions et permet de r´aliser un premier interpr`te. Enfin au chapitre 5, nous pr´sentons le
    e                                          u e
syst`me de type du langage et la preuve de sˆret´ du typage.
                   e                       e        `                        e e
    Dans la troisi`me partie, nous nous int´ressons a l’implantation du mod`le r´actif et en parti-
                                                                      e
culier aux techniques d’ordonnancement efficaces. Le chapitre 6 pr´sente Glouton, la premi`re    e
 e             e                                           e   e                        e e
s´mantique d´crivant une implantation efficace du mod`le r´actif que nous avons r´alis´e. Ce
          ee         `
travail a ´t´ fait a l’origine sur Junior en s’inspirant de Simple, l’implantation de Laurent
                                       e
Hazard. Dans le chapitre 7, nous pr´sentons Lk le langage vers lequel nous compilons Reac-
                e                             `      e
tiveML. La s´mantique que nous donnons a Lk d´crit la technique d’ordonnancement utilis´e        e
                                                                        e
en ReactiveML. Nous terminons cette partie au chapitre 8 par l’´tude de l’implantation en
                                           e         e                      e
Ocaml de Lk . Dans ce chapitre, nous pr´sentons ´galement une biblioth`que Ocaml pour la
                   e
programmation r´active.
              e                                      e
    La quatri`me partie porte sur les applications ´crites en ReactiveML et sur les mesures
                            e
de performances. Nous d´taillons au chapitre 9 l’implantation d’un simulateur de protocoles
                        e                                        ee e e
de routage dans les r´seaux mobiles ad hoc. Ce simulateur a ´t´ r´alis´ en collaboration avec
  e        e
l’´quipe R´seaux et Performances du Laboratoire d’Informatique de Paris 6 (LIP6).
             e                      e `                                               e
    La derni`re partie est consacr´e a des discussions. Dans le chapitre 10, nous ´tudions les
choix faits dans la conception du langage par rapport aux autres implantations du mod`le        e
 e                         e                                   `
r´actif. Le chapitre 11 pr´sente des modifications en cours et a venir du langage. Le chapitre 12
                             e                        e
conclut le document et pr´sente des perspectives d’´volution de ReactiveML.
                                    Chapitre 2

             e
           Pr´sentation de ReactiveML

                    e
    ReactiveML ´tend Ocaml avec des constructions de programmations concurrentes bas´es       e
            e e                                                       o
sur le mod`le r´actif. Il ajoute la notion de processus au langage hˆte. Les processus sont des
                    e                                                e      e e
fonctions dont l’ex´cution peut prendre du temps : elles peuvent ˆtre ex´cut´es sur plusieurs
                                                             ee                     e
instants. Par opposition, les fonctions Ocaml sont consid´r´es comme instantan´es. En faisant
                                                     e
l’analogie avec les circuits, les fonctions instantan´es correspondent aux circuits combinatoires
                                                e
et les processus correspondent aux circuits s´quentiels [72].
                   e                                 `                            e
    Ce chapitre pr´sente le langage ReactiveML a travers des exemples. La pr´sentation s’ap-
puie sur une bonne connaissance de Ocaml.


2.1       e          a
        Pr´sentation ` travers des exemples simples
     ReactiveML est une extension de Ocaml ce qui signifie que tout programme Ocaml
est un programme ReactiveML valide (dans l’implantation actuelle, les objets, les labels et
                                      e e                e
les foncteurs ne sont pas encore int´gr´s). Le langage ´tant une extension de Ocaml, cette
   e          e                              e               o
pr´sentation d´taille les constructions ajout´es au langage hˆte.

2.1.1    e                                          e
        D´finition de processus et composition parall`le
           c
   Commen¸ons avec comme premier exemple le processus hello_world. Ce processus affiche
                                                                             e
hello au premier instant et world au second. L’instruction pause suspend l’ex´cution du pro-
             a
gramme jusqu’` l’instant suivant :
let process hello_world =
  print_string "hello ";
  pause;
  print_string "world"
val hello_world : unit process
                                 e                                             e
Les lignes en italique sont donn´es par le compilateur. Ici, le compilateur inf`re que hello_world
                                                             e
est un processus dont la valeur de retour est la valeur unit´ (()).
                                    e
    Un programme ReactiveML d´finit un ensemble de valeurs et de processus. Le processus
          ` e             e       e                                                    e e
principal a ex´cuter est d´termin´ au moment de la compilation. Si le processus pr´c´dent est
 e
d´fini dans le fichier hello.rml, la ligne de compilation est alors :

  rmlc -s hello_world hello.rml

                                               27
28                                    e
                                 2. Pr´sentation de ReactiveML

                     e e
Le compilateur rmlc g´n`re le fichier hello.ml qu’il faut compiler avec un compilateur Ocaml :
     ocamlc -I ‘rmlc -where‘ unix.cma rml_interpreter.cma hello.ml
                                                 `      e             e
    Il est possible d’appeler un autre processus a l’int´rieur d’une d´finition de processus. L’ap-
                                        e                                              e
plication de processus se fait avec l’op´rateur run. Par exemple le processus qui ex´cute deux
                                     e    e
instances de hello_world en parall`le s’´crit :
let process hello_world2 =
  run hello_world || run hello_world
val hello_world2 : unit process
                        e                          e                       e
Le symbole || est l’op´rateur de composition parall`le synchrone. Donc l’ex´cution du processus
hello_world2 affiche toujours : hello hello worldworld. Il ne peut jamais y avoir world
      e                                         e                   e
affich´ avant hello car les deux branches parall`les partagent une ´chelle de temps commune
                               e                                                  e
et les deux hello sont affich´s au premier instant alors que les world sont affich´s au second.
                                                          e           e           e
Par ailleurs, les lettres de deux mots ne peuvent jamais ˆtre intercal´es car l’ex´cution d’une
expression Ocaml (comme print_string "hello") est toujours atomique : il n’y a pas de
                                                                                        ` e
concurrence au niveau des expressions Ocaml. Ainsi, il n’y a pas de sections critiques a d´finir
                        e
contrairement au mod`le des threads.
Remarque :
                         e                                                   e
   La composition parall`le est commutative. Donc dans l’exemple suivant, mˆme si les deux
                           e                                            e
   affectations sont des op´rations atomiques, la valeur de x n’est pas d´terministe :
         let x = ref 0 in (x := 4) || (x := 2)
                          e         e e
   Les processus peuvent ˆtre param´tr´s par un ensemble de valeurs. Le processus pause_n
            e                           e
suspend l’ex´cution d’une branche parall`le pendant n instants :
let process pause_n n =
  for i = 1 to n do pause done
val pause_n : int -> unit process
                                        e
    Lorsqu’un processus termine son ex´cution, il retourne une valeur. Ainsi, le processus fact
                                         e
faisant une multiplication par instant s’´crit :
let rec process fact n =
  pause;
  if n <= 1 then
    1
  else
    let v = run (fact (n-1)) in
    n * v
val fact : int -> int process
         e                        e
     De mˆme, le processus fibo s’´crit :
let rec process fibo n =
  pause;
  if n < 2 then 1
  else
    let f1 = run (fibo (n-1)) and f2 = run (fibo (n-2)) in
    f1 + f2
val fibo : int -> int process
                              e          `
                       2.1. Pr´sentation a travers des exemples simples                           29

                                                  e                                    e
let/and/in est une construction de mise en parall`le. Ici, chaque instance de fibo ex´cute deux
                                 e        a                  e      `                       e
instances du processus en parall`le jusqu’` ce que n soit inf´rieur a 2. Ainsi, si n est sup´rieur
`
a 1, le calcul de fibo n prend n + 1 instants.
                                               e
    Si la construction let/and/in est remplac´e par deux let/in, les calculs de f1 et f2 ne
            e e             e           e                                                e
sont pas ex´cut´s en parall`le mais en s´quence. Dans ce cas, le nombre d’instants n´cessaires
                                    e      `                                             e
pour le calcul de fibo n avec n sup´rieur a 1 est la somme des nombres d’instants n´cessaires
pour le calcul de f1 et f2 plus un.
Remarque :
                                                                      e
   Les constructions let/in et let/and/in sont fondamentalement diff´rentes. Le let/in
                                    e
   est une construction de mise en s´quence alors que let/and/in est une construction de
                 e
   mise en parall`le.
                          e1 ;e2 ≡ let = e1 in let x = e2 in x
                          e1 ||e2 ≡ let = e1 and = e2 in ()


2.1.2    Les communications
                                            e                                   e   e e
   Les communications entre processus parall`les se font par diffusion instantan´e d’´v´nements.
               e    e                                                         e
Un signal peut ˆtre ´mis (emit), attendu (await) et on peut tester sa pr´sence (present).
        c                                                                             e
Commen¸ons avec le processus is_present qui affiche Present si le signal x est pr´sent (les
      e                                e
param`tres du type event seront expliqu´s plus tard) :
let process is_present x =
  present x then print_string "Present"
val is_present : (’a, ’b) event -> unit process
La notation present <signal> then <expr> est un raccourci pour present <signal> then
<expr> else ().
                            e                   e
   Le programme dual a une s´mantique un peu diff´rente :
let process is_absent x =
  present x else print_string "Absent"
val is_absent : (’a, ’b) event -> unit process
                     e                     e                                                 e
Si le signal x est pr´sent, rien n’est affich´. S’il est absent, l’affichage de Absent est retard´ d’un
                                                          e e
instant car ReactiveML suit les restriction du mod`le r´actif [18].
     ´                                        e                   `
    Ecrivons maintenant un processus qui ´met le signal z a chaque fois que x et y sont syn-
             e           e
chrones (pr´sents au mˆme instant) :
let process together x y z =
  loop
    present x then present y then (emit z; pause)
  end
val together :
  (’a, ’b) event -> (’c, ’d) event -> (unit, ’e) event -> unit process
                                                                                       e
Ici, si x ou y sont absents, la branche else implicite du present est emprunt´e. Ceci est
e          ` e
´quivalent a ex´cuter une instruction pause. Ainsi nous pouvons remarquer que quelque soit le
                      e                                                e                    e       e
statut de x et y, l’ex´cution du corps de la boucle n’est pas instantan´. Cela garantie la r´activit´
                                                          e                            e
du programme. En effet, s’il y a une boucle instantan´e dans un programme, l’ex´cution d’un
                                                                                        e
instant ne termine jamais, et donc les instants peuvent pas passer : le temps “s’arrˆte”.
30                                    e
                                 2. Pr´sentation de ReactiveML

                              e
    Voyons enfin l’exemple du d´tecteur de front haut. Le comportement du processus edge est
  e                                        e              e            `             e e
d’´mettre le signal s_out quand s_in est pr´sent et qu’il ´tait absent a l’instant pr´c´dant :
let process edge s_in s_out =
  loop
    present s_in then pause
    else (await immediate s_in;
         emit s_out)
  end
val edge : (’a, ’b) event -> (unit, ’c) event -> unit process

                                 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
                         s_in

                         s_out


                       e                       e
Tant que s_in est pr´sent, s_out n’est pas ´mis. Quand s_in devient absent, s_out n’est
             e                  o                              `
toujours pas ´mis, mais le contrˆle passe par la branche else. A l’instant suivant, le processus
                        e                                                e
se met en attente de l’´mission de s_in. Maintenant, quand s_in est pr´sent, s_out est ´mise
      e      e                      `             e e                 e
(s_in ´tait n´cessairement absent a l’instant pr´c´dant). Le mot cl´ immediate indique que
          e    `            u            e
s_out est ´mis a l’instant o` s_in est pr´sent.
Remarque :
                                e                   `                  e
   La construction await ex´cute sa continuation a l’instant suivant l’´mission du signal alors
                         e                                e                      `
   que la version imm´diate de cette construction qui ex´cute sa continuation a l’instant o`  u
                  e
   le signal est ´mis.
                                                                     e
   Il faut faire attention : la construction await/immediate est la mˆme que celle d’Esterel,
                                e            e
   mais la version non imm´diate est diff´rente. En Esterel, nous avons :

                            await s     ≡    pause; await immediate s

                                             e
     alors qu’en ReactiveML, la pause est apr`s le await :

                            await s     ≡    await immediate s; pause

     Nous discuterons de ce choix chapitre 10.3.5.

2.1.3                          o
        Les structures de contrˆle
                                                                     o
    On introduit maintenant les deux principales structures de contrˆle du langage : la construc-
                              e
tion do e when s suspend l’ex´cution de e lorsque s est absent et do e until s done interrompt
  e                e                           e
d´finitivement l’ex´cution de e quand s est pr´sent. On illustre ces deux constructions avec un
                                      o              u                    e e
processus suspend_resume qui contrˆle les instants o` un processus est ex´cut´. Pour reprendre
                e                                                  `
l’analogie donn´e dans [10], la construction do/until correspond a la commande Unix Ctrl-c
et le processus suspend_resume a le comportement du couple de commande Ctrl-z et fg.
                        e                                 e e
    On commence par d´finir le processus sustain param´tr´ par un signal s. sustain ´met s e
`
a chaque instant :
let process sustain s = loop emit s; pause end
val sustain : (unit, ’a) event -> unit process
                            e          `
                     2.1. Pr´sentation a travers des exemples simples                       31

           e                      e
    Nous d´finissons un autre op´rateur typique : switch. Ce processus est un automate de
            `      e                  e e
Moore [77] a deux ´tats. Il est param´tr´ par deux signaux, s_in et s_out. Son comportement
                   e                                                                    e
est de maintenir l’´mission de s_out tant que s_in est absent. Puis, lorsque s_in est pr´sent,
                       e                       a                  e    `
le processus suspend l’´mission de s_out jusqu’` ce que s_in soit ´mis a nouveau. Le processus
                         e
retourne alors dans son ´tat initial.
let process switch s_in s_out =
  loop
    do run (sustain s_out) until s_in done;
    await s_in
  end
val switch : (’a, ’b) event -> (unit, ’c) event -> unit process

                      s_in                       1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
             1                   2       s_in
           s_out
                                         s_out
                      s_in


          e                                       e                                    e e
    On d´finit maintenant le processus d’ordre sup´rieur suspend_resume. Il est param´tr´ par
                                                          e                  `        e
un signal s et un processus p. Ce processus commence l’ex´cution de p. Puis, a chaque ´mission
                                   e
de s, il suspend puis reprend l’ex´cution de p alternativement. On implante ce processus par
                     e                          e
la composition parall`le (1) d’un do/when qui ex´cute le processus p seulement quand le signal
               e               e                                      o    e
active est pr´sent et (2) l’ex´cution d’un processus switch qui contrˆle l’´mission de active
avec le signal s.
let process suspend_resume s p =
  signal active in
  do run p when active
  ||
  run (switch s active)
val suspend_resume : (’a, ’b) event -> ’c process -> unit process
                        e
On peut constater que mˆme si p termine le processus suspend_resume ne termine pas car le
                                                             e   e                    e
processus switch ne termine jamais. De plus, on ne peut pas r´cup´rer la valeur calcul´e par p.
                                           ee
Afin de corriger ces deux points, on peut r´´crire le processus suspend_resume de la fa¸on  c
suivante :
let process suspend_resume s p =
  signal active, kill in
  let v =
    let x = do run p when active in
    emit kill;
    x
  and _ = do run (switch s active) until kill done in
  v
val suspend_resume : (’a, ’b) event -> ’c process -> ’c process
                                           e    e                   e          e
La construction let/and/in permet de r´cup´rer des valeurs calcul´es en parall`le.
                 e       e                                                e
    Ce processus ´tant tr`s utile, la construction control/with qui a le mˆme comportement a
ee       e                                                         e
´t´ ajout´e au langage. Le processus suspend_resume peut donc s’´crire simplement :
32                                           e
                                        2. Pr´sentation de ReactiveML

                            emit s v1
                                                           await s(x) in ...
                            emit s v2                  v
                                               f
                                                   d
                            emit s vn                      await s(y) in ...
                                 v = (f vn ... (f v2 (f v1 d))...)



                   e                             e                                        `
Fig. 2.1 – Multi-´mission sur le signal s, combin´e avec la fonction f, donne la valeur v a
l’instant suivant.

let process suspend_resume s p =
  control
    run p
  with s
val suspend_resume : (’a, ’b) event -> ’c process -> ’c process


2.1.4                     e           e
              Signaux valu´s et multi-´mission
                  e                                       e            e e
   Nous nous int´ressons maintenant aux signaux valu´s. Ils peuvent ˆtre ´mis (emit <signal>
                                          e       e     e   ee
<value> ) et la valeur qui leur est associ´e peut ˆtre r´cup´r´e (await <signal> (<pattern> )
in <expression> ). La construction await/in (comme un let/in) introduit un nouvel identi-
                                                       e`
ficateur dans sa partie droite. Ici, ce nom est associ´ a la valeur du signal.
                                e    e
   Plusieurs valeurs peuvent ˆtre ´mises pendant un instant sur un signal, cela s’appelle de
         e                                                                           e
la multi-´mission. ReactiveML adopte une solution originale pour traiter la multi-´mission.
`     e                                               e                                e
A la d´claration du signal, le programmeur doit d´finir comment combiner les valeurs ´mises
               e
pendant un mˆme instant. Pour cela, il y a la construction suivante :
signal <name> default <value> gather <function> in <expression>
                                       e                  e
    Le comportement en cas de multi-´mission est illustr´ figure 2.1. On suppose que le signal
       e    e                     e
s est d´clar´ avec la valeur par d´faut d et la fonction de combinaison f. Si les valeurs v1, ...,
vn sont ´mises pendant un instant, tous les await re¸oivent la valeur v a l’instant suivant 1 .
         e                                              c                   `
  e   e                                   e                    e              e                e
R´cup´rer la valeur d’un signal est retard´ d’un instant pour ´viter les probl`mes de causalit´.
                         `
En effet, contrairement a Esterel, le programme suivant est causal :
await s(x) in emit s(x+1)
                                                       `
La valeur x du signal s est disponible seulement a la fin d’instant. Donc, si x = 41 pendant
                                   e            `
l’instant courant, le programme ´met s(42) a l’instant suivant.
                         e                                   e
    Le type des valeurs ´mises sur un signal et le type du r´sultat de la fonction de combinaison
          e       e
peuvent ˆtre diff´rents. Cette information est contenue dans le type du signal. Si t1 est le type
             e
de la valeur ´mise sur le signal s et t2 celui de la combinaison, alors s a le type (t1,t2) event.
                 e                                                                   e
    Si on veut d´finir le signal sum qui calcule la somme de toutes les valeurs ´mises, alors le
            e      e   e         c
signal doit ˆtre d´clar´ de la fa¸on suivante :
signal sum default 0 gather (+) in ...
sum : (int,int) event
     1
         v = (f vn ... (f v2 (f v1 d))...)
                             e          `
                      2.1. Pr´sentation a travers des exemples simples                        33

Dans ce cas, le programme await sum(x) in print_int x attend le premier instant o` x estu
  e            `                                                  e
pr´sent. Puis, a l’instant suivant, il affiche la somme des valeurs ´mises sur x.
                                                  e
    Un signal peut collecter toutes les valeurs ´mises pendant un instant. Pour cela, il y a la
          e
syntaxe sp´ciale :
signal s in ...
qui est un raccourci pour :
signal s default [] gather fun x y -> x :: y in ...
s : (’a, ’a list) event
                    e                                                                       e
Ici, la valeur par d´faut est la liste vide et la fonction de combinaison ajoute une valeur ´mise
`                       eae
a la liste des valeurs d´j` ´mises.
                                                       e       e                            e
     Donnons un exemple qui utilise les signaux valu´s. On d´finit le processus run_n qui ex´cute
                                                                                          e
un processus p pendant au plus n instants. Le processus affiche Execution aborted si l’ex´cution
de p prend plus de n instants et Execution finished si p termine normalement. Ce processus
                                         u                       e                     ` e
utilise la construction do/until/-> o` la partie droite de la fl`che est le traitement a ex´cuter
           e
en cas pr´emption.
let process run_n n p =
  signal finished default false gather (or) in
  do
    run p;
    emit finished true;
    pause;
    ||
    run (pause_n (n-1));
    emit finished false;
    pause;
  until finished(b) ->
    if b then
      print_string "Execution finished"
    else
      print_string "Execution aborted"
  done
val run_n : int -> ’a process -> unit process
              e e            e
Ici, p est ex´cut´ en parall`le avec un processus qui attend n instants. Le premier processus
                     e       e
qui termine son ex´cution ´met le signal finished pour tuer l’autre processus. La valeur du
                                 e                      e              ee
signal finished est alors utilis´e pour savoir si l’ex´cution de p a ´t´ interrompue ou pas. Si
    e                                                                     e e
l’ex´cution de p prend exactement n instants, les deux branches parall`les ´mettent finished
           e
dans le mˆme instant avec les valeurs true et false. Dans ce cas, la fonction de combinaison
                                                          e
associe true au signal pour indiquer que p s’est termin´ normalement.
                                               e    e                   e `
    Il existe deux autres constructions pour r´cup´rer la valeur associ´e a un signal : pre ?s et
                                        e   e             e                  e e
await/one/in. L’expression pre ?s r´cup`re instantan´ment la valeur pr´c´dente d’un signal.
                        eee                          e                        e
Si le signal n’a jamais ´t´ ´mis, cette expression s’´value en la valeur par d´faut du signal.
                                                 e     e                        e
    L’expression await one s(x) in ... ne r´cup`re pas la valeur combin´e du signal, mais
                   e
une des valeurs ´mises. Comme pour la construction await/in, le corps du await/one/in
       e e `                       e                        e                            e
est ex´cut´ a l’instant suivant l’´mission. Mais il existe ´galement une version imm´diate de
34                                    e
                                 2. Pr´sentation de ReactiveML

                                                                                e
cette construction. Ainsi l’expression await immediate one s(x) in ... ex´cute son corps a      `
                   e
l’instant ou s est ´mis.
                                                    e                                      e
    Il faut noter que cette construction n’est pas d´terministe. Si plusieurs valeurs sont ´mises
                                      e   ee                                   e e
sur s pendant un instant, la valeur r´cup´r´e par await/one/in n’est pas sp´cifi´e.
Remarque :
                                                   e          e
   Dans l’implantation actuelle, await/one/in peut ˆtre utilis´ uniquement si le signal est
    e    e
   d´clar´ sans fonction de combinaison.


2.1.5                                e         e                  e
        Aspects dynamiques, ordre sup´rieur et ´chappement de port´e
                                                                    e      e
   Parmi les aspects dynamiques, il y a la reconfiguration de syst`mes r´actifs. Une forme
                                   e                                e           e
simple de reconfiguration est la r´initialisation de processus. Un op´rateur de r´initialisation
     e            e `                                                             e
peut ˆtre implant´ a partir de la construction do/until. Le processus suivant r´initialise le
            `                    u                   e
processus p a tous les instants o` le signal s est pr´sent :
let rec process reset s p =
  do
    run p
  until s(_) -> run (reset s p) done
val reset : (’a, ’b) event -> ’c process -> ’c process
                   e                                                     `
Ce processus est r´cursif. Il appelle une nouvelle instance de reset a chaque fois que s est
   e
pr´sent.
         e
     On d´finit maintenant le processus replace qui permet de remplacer un processus p par un
             `                       e                   e
processus p’ a chaque fois que s est ´mis. Les processus ´tant des valeurs (comme les fonctions),
     e                                                e         e
la d´finition du processus qui doit remplacer p peut ˆtre envoy´ sur le signal s.
let rec process replace s p =
  do
    run p
  until s(p’) -> run (replace s p’) done
val replace : (’a, ’b process) event -> ’b process -> ’b process
                     e                                  e
Ce processus a la mˆme structure que reset. La diff´rence est que la fonction de traitement
  e              e    e       e                               ` e
d’´chappement r´cup`re la d´finition du nouveau processus a ex´cuter.
    Nous encodons maintenant la construction Jr.Dynapar("add", Jr.Halt()) de Junior.
                       ee                                                    e
Cette construction a ´t´ introduite dans [1] pour la programmation de syst`mes d’agents. Ce
            c                                             e             e
processus re¸oit sur le signal add des processus qu’il ex´cute en parall`le.
let rec process dynapar add =
  await add (p) in
  run p
  ||
  run (dynapar add)
val dynapar : (’a, process) event -> unit process
          e                              e
   Nous d´finissons le processus send qui ´met le processus p1 sur le signal add et attend un
                       e             e                                                   e
acquittement de son ex´cution pour ex´cuter le processus p2. Le processus p2 utilise le r´sultat
            e
rendu par l’´valuation de p1.
                                2.2. Deux exemples complets                                   35

let process send add p1 p2 =
  signal ack in
  emit add (process (let v = run p1 in emit ack v));
  await immediate one ack(res) in
  run (p2 res)
val send :
  (unit process, ’a) event -> ’b process -> (’b -> ’c process) -> ’c process

                                                                    e
L’expression process (let v = run p1 in emit ack v) est la d´finition d’un processus ano-
             e             e         e
nyme qui ex´cute p1 et ´met le r´sultat rendu par p1 sur le signal ack. Dans ce processus, le
                                   e                          e                 e      `
signal ack est libre lorsqu’il est ´mis sur add. Comme la port´e de add est sup´rieure a celle de
                  e                   e             e    e
ack, ce dernier ´chappe de sa port´e. C’est un ph´nom`ne classique du π-calcul [75].
       a ` e                           e                                 e e e ee
    Grˆce a l’´chappement de port´e, un canal de communication priv´ a ´t´ cr´´ entre send
                  e
et le processus ´mis sur add. La liaison statique des noms garantit qu’il ne peut pas y avoir
                         e                 e
d’autres processus qui ´mettent ou qui ´coutent sur ack.
               e                         e        e
    La mobilit´ du π-calcul peut ainsi ˆtre simul´e. Reprenons l’exemple du chapitre 9.3 de [75].
                                   e e            e
Trois processus p, q et r sont ex´cut´s en parall`le. D’une part p et q peuvent communiquer en
utilisant un signal x et d’autre part p et r communiquent par le signal z. Les processus p et q
          e     e
peuvent ˆtre d´finis de telle sorte que q et r puissent communiquer en utilisant z.
let process p x z =
  emit x z;
  run (p’ x)
val p : (’a, ’b) event -> ’a -> unit process

let process q x =
  await one x(y) in
  run (q’ y)
val q : (’a, ’a list) event -> unit process

let process r z = ...
val r : (’a, ’b) event -> unit process

let process mobility x z =
  run (p x z) || run (q x) || run (r z)
val mobility :
  ((’a, ’b) event, (’a, ’b) event list) event ->
  (’a, ’b) event -> unit process



2.2     Deux exemples complets
2.2.1   Le banc de poissons
           e                                           e
    Nous d´crivons maintenant l’implantation d’un probl`me de simulation. Nous voulons simu-
ler des poissons qui nagent dans un aquarium.
                  c         e
    Nous commen¸ons par d´finir le type position comme un couple d’entiers et le type frame
comme une paire de positions.
36                                    e
                                 2. Pr´sentation de ReactiveML

type position = int * int
type frame = position * position
             e                                          a                                  e e
Puis, nous d´finissons d’abord un processus button (` cliquer avec une souris). Il est param´tr´
                  e
par ses coordonn´es (frame) et deux signaux (mevent et oclick). On suppose l’existence d’une
                                                             e
fonction draw qui dessine un bouton et une fonction bool´enne inside (x,y) frame qui teste
                              e               `       e               e
quand le point de coordonn´es (x,y) est a l’int´rieur des coordonn´es de frame. Le signal
      e               e                                    e
d’entr´e mevent repr´sente la souris. Ce signal est pr´sent quand le bouton de la souris est
       e                    e                                                           e
appuy´ et la valeur associ´e au signal est la position de souris. Le processus button ´met le
                                            `      e
signal de sortie oclick si la souris clique a l’int´rieur du bouton.
let process button frame mevent oclick =
  draw frame;
  loop
    await mevent (pos) in
    if inside pos frame then emit oclick;
  end
val button :
  frame -> (’a, position) event -> (unit, ’b) event -> unit process
                                                    e                                    e
    Un poisson est un processus ayant cinq param`tres. border, init_pos et size d´finissent
les limites de l’aquarium, la position initiale du poisson et sa taille. Avec le signal others un
           c                                                   e                              c
poisson re¸oit en continu la position de tous les poissons pr´sents dans l’aquarium et il re¸oit
la position de la souris avec mevent.
let process fish border init_pos size others mevent =
  (* start from an initial position *)
  signal kill in
  let pos = ref init_pos in
  do
    loop
      (* moves according to some law *)
      emit others (!pos);
      await others (o) in
      clear_fish !pos size;
      pos := law !pos border o;
      draw_fish !pos size;
    end
    ||
    loop
      await mevent (mouse_pos) in
      if inside_fish mouse_pos !pos size then emit kill;
    end
  until kill done;
  clear_fish !pos size
val fish :
  frame -> position -> int ->
  (position, position list) event -> (’a, position) event -> unit process
                                                  e
Le comportement d’un poisson est le suivant : il d´finit d’abord un signal local kill permettant
                                2.2. Deux exemples complets                                    37

                                              e                e
de supprimer le poisson et une variable imp´rative pos repr´sentant sa position puis il effectue
                         e          e                       e           `     e
deux actions en parall`le de mani`re cyclique. La premi`re consiste a (1) ´mettre sa position,
     e     e
(2) r´cup´rer la position des autres poissons, (3) calculer sa nouvelle position selon la loi law.
L’autre comportement cyclique surveille le signal mevent et si la souris clique sur le poisson,
                         e                                                               e
alors le signal kill est ´mis. Ces deux actions sont incluses dans une construction de pr´emption
do/until de sorte que le processus fish termine quand kill est pr´sent.e
             e
    Nous d´finissons maintenant un banc de poissons. Ce banc (shoal) est agrandi avec un
                                                     e
nouveau poisson chaque fois que le signal add est ´mis.
let rec process shoal frame add others mevent =
  await add;
  (* the initial position is taken randomly *)
  let init_pos = random_pos frame in
  run (fish frame init_pos ((Random.int 10)+1) others mevent)
  ||
  run (shoal frame add others mevent)
val shoal :
  frame -> (’a, ’b) event ->
  (position, position list) event -> (’c, position) event -> unit process
                                                  e                    e                    e
On peut remarquer que shoal est un processus r´cursif. Lorsque add est ´mis, le processus cr´e
                            e
un poisson et se rappelle r´cursivement pour attendre de nouveau le signal add. Il n’y a pas
    e                 e                     e                                 e e
de r´cursion instantan´e car await add ex´cute sa continuation un instant apr`s l’´mission du
signal.
    Maintenant, un aquarium est un processus qui contient un banc de n poissons et un bouton
pour en ajouter. Tous les poissons utilisent le signal others pour communiquer leur position.
                                                   e
Ce signal doit donc collecter toutes les positions ´mises.
let process aquarium ((x_min,y_min),(x_max,y_max)) mevent n =
  let x_sep = x_min + (x_max-x_min) / 10 in
  (* compute the border for the water *)
  let shoal_frame = (x_sep,y_min),(x_max,y_max) in
  (* compute the border for the create button *)
  let but_frame = (x_min,y_min),(x_sep,y_max) in
  signal others default [] gather fun x y -> x :: y in
  signal add in
  run (button but_frame mevent add)
  ||
  run (shoal shoal_frame add others mevent)
  ||
  for i = 1 to n dopar
    run (fish shoal_frame (random_pos shoal_frame) (random_size())
          others mevent)
  done
val aquarium : frame -> (’a, position) event -> int -> unit process
                                        e
Ce processus fait donc la mise en parall`le d’un processus button, d’un processus shoal et de
n processus fish.
                                                                     e                  e
   Finalement, le programme principal est un processus sans param`tre. Ce processus d´finit
38                                    e
                                 2. Pr´sentation de ReactiveML

                                                                  e
d’abord quelques constantes puis appelle le processus mouse (qui d´finit les signaux de souris)
                                  e
et le processus aquarium en parall`le.
let process main =
  Graphics.open_graph "";
  let border = ((0, 0), (Graphics.size_x(), Graphics.size_y())) in
  signal mevent default (0,0) gather fun x y -> x in
  run (mouse mevent)
  ||
  run (aquarium border mevent 10)
val main : unit process


2.2.2               ´       e
        Le crible d’Eratosth`ne
                                          ´        e
    Terminons avec l’exemple du crible d’Eratosth`ne tel qu’on peut le trouver dans [59]. C’est
                                      e
un exemple classique de l’approche r´active (cf. [20] par exemple). Il reprend l’utilisation des
                                 e              e
signaux, de la composition parall`le et de la cr´ation dynamique.
         e                                          e e                              `
    On d´finit d’abord le processus integers qui g´n`re la suite des entiers naturels a partir de
la valeur de n.
let rec process integers n s_out =
  emit s_out n;
  pause;
  run (integers (n+1) s_out)
val integers : int -> (int, ’a) event -> ’b process
               e     `                                                    e                 e
Un entier est ´mis a chaque instant sur le signal s_out. Il n’y a pas de r´cursion instantan´e
  a `
grˆce a l’instruction pause.
            e
   Nous d´finissons maintenant le processus filter qui supprime les multiples d’un nombre
premier.
let process filter prime s_in s_out =
  loop
    await one s_in(n) in
    if n mod prime <> 0 then emit s_out n
  end
val filter : int -> (int, int list) event -> (int, ’a) event -> unit process
                                    e                              `
   Maintenant, le processus shift cr´e un nouveau processus filter a chaque fois qu’un
                            e
nouveau nombre premier est d´couvert.
let rec process shift s_in s_out =
  await one s_in(prime) in
  emit s_out prime;
  signal s default 0 gather fun x y -> x in
  run (filter prime s_in s) || run (shift s s_out)
val shift : (int, int list) event -> (int, ’a) event -> unit process
                 e
    Enfin, nous d´finissons le processus output qui affiche les nombres premiers et le processus
principal sieve.
                               2.2. Deux exemples complets                                  39

let process output s_in =
  loop
    await one s_in (prime) in
    print_int prime
  end
val output : (int, int list) event -> unit process

let process sieve =
  signal nat, prime in
  run (integers 2 nat)
  ||
  run (shift nat prime)
  ||
  run (output prime)
val sieve : unit process
                                                                                 e
Les fonctions de combinaison de nat et prime ne gardent qu’une seule des valeurs ´mises pendant
l’instant.


 e   e
R´sum´
                                                           ee       e `
   Nous reprenons ici l’ensemble des constructions qui ont ´t´ ajout´es a Ocaml.
 e
D´finition de processus
       let process <id> = <expr> in <expr>
       let process <id> <pattern> ... <pattern> = <expr> in <expr>
       process <expr>

           e                                                   e
     Les d´finitions de processus sont introduites par le mot cl´ process. Un processus peut
     e          e                                               e
     ˆtre nomm´ avec la construction let process ou on peut d´finir des processus anonymes
     avec la notation process <expr> .
Instructions de base
       nothing
       pause
       halt
       run <process>

                  e          `                        e
     nothing est ´quivalent a (). pause suspend l’ex´cution pour un instant, halt suspend
         e                              e
     l’ex´cution pour toujours et run ex´cute un processus.
Compositions
       <expr> ; <expr>
       <expr> || <expr>
       let <pattern> = <expr> and <pattern> = <expr> in <expr>

                                      e                        e
     En ReactiveML, on peut ex´cuter deux expressions en s´quence ou en parall`le. Lae
                                                               e       e   e
     construction let/and/in calcule deux expressions en parall`le et r´cup`re leurs valeurs
                                    e
     pour ensuite calculer la troisi`me expression.
40                                  e
                               2. Pr´sentation de ReactiveML

 e
D´clarations de signaux
       signal <id> in <expr>
       signal <id>, ..., <id> in <expr>
       signal <id> default <value> gather <function> in <expr>

                               ` e                                         e
     Ces constructions servent a d´clarer de nouveaux signaux. Lors de la d´claration, on peut
      e                                      e
     d´finir comment combiner les valeurs ´mises pendant un instant sur un signal avec la
     construction signal/gather. Si on ne donne pas de fonction de combinaisons, le compor-
                                                          e
     tement du signal est de collecter toutes les valeurs ´mises
´
Emission de signaux
       emit <signal>
       emit <signal> <value>

          e                                         e                          e
     Les ´missions se font par diffusion instantan´e. Ainsi, un signal est pr´sent ou absent
     pendant un instant mais il ne peut pas avoir les deux statuts. La notation emit <signal>
                           e
     est un raccourci pour ´mettre un signal avec la valeur () (unit).
Statut d’un signal
       present <signal> then <expr> else <expr>
       await <signal>
       await immediate <signal>
       pre <signal>

                                                                        e
     L’expression present teste le statut du signal. Si le signal est pr´sent, la branche then
           e e             e                                   e e `
     est ex´cut´e instantan´ment, sinon la branche else est ex´cut´e a l’instant suivant.
                                              e                 `
     L’expression await s attend que s soit ´mis et termine a l’instant suivant. Alors que
                                                        e                          e
     l’expression await immediate s attend que s soit ´mis et termine instantan´ment.
                                           e        ee                               e
     Comme Esterel, la version non imm´diate a ´t´ choisi comme version par d´faut pour
             e
     que la s´quence
       await s; await s

     attende deux occurrences de s. Alors que await immediate s; await immediate s est
     e          `
     ´quivalent a await immediate s.
                          e                               eee      `             e e
     L’expression pre s s’´value en true si le signal s a ´t´ ´mis a l’instant pr´c´dent ou en
     false sinon.
Valeur d’un signal
       await one <signal> (<pattern>) in <expr>
       await immediate one <signal> (<pattern>) in <expr>
       await <signal> (<pattern>) in <expr>
       pre ?<signal>

                                               e
     La construction await/one/in attend l’´mission d’un signal pour lier le pattern avec une
                 e                  e
     des valeurs ´mises. En cas d’´mission multiple sur un signal dans un instant, le choix
                                e e                      e            e
     de la valeur n’est pas sp´cifi´. Le pattern peut ˆtre alors utilis´ dans la partie droite
                                                                    e e
     du await one/in. Comme pour await, la partie droite est ex´cut´e un instant apr`s lae
      e                                     e          e
     r´ception du signal, sauf si on a ajout´ le mot cl´ immediate.
                                2.2. Deux exemples complets                                     41

                            e                        e    e `
     Le await/in attend l’´mission d’un signal et r´cup`re a la fin de l’instant la combinaison
                  e
     des valeurs ´mises pendant l’instant sur le signal. Le corps du await/in est ex´cut´ a e e `
                         e                                               e
     l’instant suivant l’´mission du signal. Pour des raisons de causalit´, il n’y a pas de version
          e
     imm´diate de cette construction.
                                      e                e `                        e ee
     L’expression pre ?s est la derni`re valeur associ´e a s. Tant que s n’a pas ´t´ ´mis, pre ?s
         e    `                 e         e `      e
     est ´gal a la valeur par d´faut donn´e a la d´claration du signal.
  e
It´rateurs
       loop <expr> end
       while <expr> do <expr> done
       for <id> = <expr> [ to | downto ] <expr> do <expr> done
       for <id> = <expr> [ to | downto ] <expr> dopar <expr> done
     loop est la boucle infinie. while et for/do sont les boucles classiques. Ces constructions
       e                                              e
     ex´cutent plusieurs instances de leur corps en s´quence. Au contraire, la construction
                   e                                       e
     for/dopar ex´cute les instances de son corps en parall`le.
                   o
Structures de contrˆle
       do <expr> when <signal>
       control <expr> with <signal>
       do <expr> until <signal> done
       do <expr> until <signal>(<pattern>) -> <expr> done
                                                                                   e
     do/when et control/with sont des constructions de suspension. Le do/when ex´cute son
                                            e
     corps seulement quand le signal est pr´sent. control/with alterne entre le mode actif et
                                            e
     suspendu chaque fois que le signal est ´mis.
                          e                        e     e                     `
     La construction de pr´emption do/until arrˆte l’ex´cution de son corps a la fin d’ins-
                               e                                        e
     tant quand le signal est ´mis. La seconde forme de do/until ex´cute un traitement
       e                           e
     d’´chappement lorsqu’il y a pr´emption.
                                    e
                               Deuxi`me partie

             e
         La s´mantique de ReactiveML

3     e
    S´mantique comportementale                                                                                                         45
    3.1 Le noyau du langage . . . . . . . . . . . . . . . . . . . . . . . . .                      .   .   .   .   .   .   .   .   .   45
                 e
        3.1.1 D´finitions . . . . . . . . . . . . . . . . . . . . . . . . . .                       .   .   .   .   .   .   .   .   .   45
        3.1.2 Traduction de ReactiveML dans le langage noyau . . . . .                             .   .   .   .   .   .   .   .   .   46
                                                e
    3.2 Identification des expressions instantan´es . . . . . . . . . . . . .                       .   .   .   .   .   .   .   .   .   48
         e          `
    3.3 S´mantique a grands pas . . . . . . . . . . . . . . . . . . . . . . .                      .   .   .   .   .   .   .   .   .   49
        3.3.1 Environnement de signaux . . . . . . . . . . . . . . . . . .                         .   .   .   .   .   .   .   .   .   49
                e
        3.3.2 S´mantique . . . . . . . . . . . . . . . . . . . . . . . . . .                       .   .   .   .   .   .   .   .   .   51
                              e
        3.3.3 Exemples de d´rivations . . . . . . . . . . . . . . . . . . .                        .   .   .   .   .   .   .   .   .   56
                                     e                 e
        3.3.4 Discussion sur les diff´rences avec la s´mantique d’Esterel                           .   .   .   .   .   .   .   .   .   58
          e                     e
    3.4 D´terminisme et unicit´ . . . . . . . . . . . . . . . . . . . . . . .                      .   .   .   .   .   .   .   .   .   59
                      ee
        3.4.1 Propri´t´s des expressions combinatoires . . . . . . . . . .                         .   .   .   .   .   .   .   .   .   62
    3.5 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .                     .   .   .   .   .   .   .   .   .   62

4     e             e
    S´mantique op´rationnelle                                                                                                          65
         e          `
    4.1 S´mantique a petits pas . . . . . . . . . . . . . .    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   65
                e          ` e
        4.1.1 S´mantique a r´duction . . . . . . . . . .       .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   65
                e
        4.1.2 R´action de fin d’instant . . . . . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   67
                  e
        4.1.3 Ex´cution d’un programme . . . . . . . .         .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   68
        ´                    e
    4.2 Equivalence avec la s´mantique comportementale         .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   68
                                      e
    4.3 Ajout des constructions non d´terministes . . . .      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   70
        4.3.1 Await/one . . . . . . . . . . . . . . . . . .    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   70
                    ee
        4.3.2 Les r´f´rences . . . . . . . . . . . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   72
    4.4 Conclusion . . . . . . . . . . . . . . . . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   73

5   Typage                                                                                                                             75
    5.1 Extension du typage de ML . . . . . . . . . . . . . . . . . .                  . . . . . . . . .                   .   .   .   75
    5.2 Preuve de sˆret´ du typage pour la r´duction → . . . . . .
                    u e                     e                                          . . . . . . . . .                   .   .   .   78
                  e
        5.2.1 Pr´servation du typage . . . . . . . . . . . . . . . . .                 . . . . . . . . .                   .   .   .   78
                                            e
        5.2.2 Les formes normales bien typ´es sont des expressions                     de fin d’instant                     .   .   .   81
    5.3 Pr´servation du typage pour la r´duction →eoi . . . . . . .
           e                            e                                              . . . . . . . . .                   .   .   .   83
                                    Chapitre 3

          e
         S´mantique comportementale

                               e                  e                         e
    Dans cette partie, nous pr´sentons le calcul r´actif sur lequel est fond´ ReactiveML. Nous
         e        `        `       e
nous int´ressons a la fois a ses s´mantiques statiques et dynamiques. Nous partons d’un noyau
  e                                                   ee
d´terministe du langage que l’on augmente avec les r´f´rences et la construction await/one/in.
                           e
Dans ce chapitre, nous pr´sentons la syntaxe abstraite du langage, l’analyse permettant d’iden-
                                 e          e                                   `
tifier les expressions instantan´es et une s´mantique dite comportementale a grand pas. Dans
                                   e           e              `               e
le chapitre 4 nous verrons une s´mantique op´rationnelle a petit pas et l’´quivalence entre les
       e                                          e               e
deux s´mantiques dynamiques. Le chapitre 5 pr´sentera le syst`me de type du langage.
                    e                                 e
    Une version pr´liminaire de ce chapitre est publi´ dans [68].


3.1     Le noyau du langage
               e                            e
   Nous consid´rons le noyau du langage. Il ´tend un noyau fonctionnel de type ML avec des
                                e
constructions de programmation r´active.

3.1.1    e
        D´finitions
                                        e
    La syntaxe des expressions (e) est d´finie figure 3.1. Nous pouvons remarquer que la construc-
                            e                     e         e
tion let/and/in n’est pas r´cursive ; pour les d´finitions r´cursives, il y a la construction rec.
                                         e                             e
La construction let/and/in est utilis´e pour la composition parall`le, elle ne peut pas ˆtre e
 e                                                  e           e
r´cursive car nous ne savons pas garantir que le r´sultat de l’´valuation d’une branche du let
                     e          e                                             e
sera disponible pour ˆtre utilis´ dans l’autre branche. Nous pouvons noter ´galement que dans
la construction
                              signal x default e1 gather e2 in e
    e                       e
e1 d´signe une valeur par d´faut et e2 une fonction de composition.
                                                                                e
    Les constantes (c) sont soit des valeurs de base comme des entiers, des bool´ens ou des
                     e
flottants, soit des op´rateurs.

                        c ::=     true | false | () | 0 | . . . | + | - | . . .

                         e
   Les valeurs (v) sont d´finies par :

                             v ::= c | n | (v, v) | λx.e | process e

                 e
Une valeur peut ˆtre une constante (c), une valeur de signal n, une paire de valeurs (v, v), une
                           e
abstraction (λx.e) ou une d´finition de processus (process e).

                                                45
46                                 e
                               3. S´mantique comportementale




     e ::=     x                                variable
             |c                                 constante
             | (e, e)                           paire
             | λx.e                               e
                                                d´finition de fonction
             |ee                                application
             | rec x = e                          e         e
                                                d´finition r´cursive
             | process e                          e
                                                d´finition de processus
             | e;e                               e
                                                s´quence
             | let x = e and x = e in e           e              e
                                                d´finitions parall`le
             | signal x default e gather e in e d´claration de signal
                                                  e
             | present e then e else e                    e
                                                test de pr´sence
             | emit e e                         e
                                                ´mission
             | pause                            attente de la fin d’instant
             | run e                               e              e
                                                ex´cution d’une d´finition de processus
             | pre e                                     e e
                                                statut pr´c´dent d’un signal
             | pre ?e                                    e e
                                                valeur pr´c´dente d’un signal
             | do e until e(x) -> e done           e
                                                pr´emption
             | do e when e                      suspension



                   Fig. 3.1 – Syntaxe abstraite du noyau de ReactiveML.

3.1.2   Traduction de ReactiveML dans le langage noyau
    Les programmes ReactiveML peuvent se traduire facilement dans ce noyau. Par exemple,
    e
la d´finition de processus
                            let process f x = e1 in e2
est un raccourci pour
                                let f = λx.process e1 in e2
                                       e                                       e e
   Un certain nombre de constructions r´actives de ReactiveML sont des formes d´riv´es des
primitives de base :
                               def
          emit e               =     emit e ()
                               def
          present e1 then e2   =     present e1 then e2 else ()
                               def
          present e1 else e2   =     present e1 then () else e2
                               def
          signal s in e        =     signal s default ∅ gather λx.λy.{x}      y in e
                               def
          do e until e1 done   =     do e1 until e(x) -> () done
                               def
          let x = e1 in e      =     let x1 = e1 and x2 = () in e   x2 ∈ f v(e)

                                       e                    e     e
Un signal pur (sans valeur) est implant´ avec un signal valu´ qui ´met la valeur ().
                                            e          `
Omettre une branche dans un present est ´quivalent a ne rien faire dans cette branche. Re-
                                                                                     e
marquons que ne pas mettre de else dans un present ne signifie pas la suppression du d´lai si
le signal est absent.
                                      3.1. Le noyau du langage                                        47

                                                                  e
La construction signal s in e est un raccourci pour la d´claration de signal qui collecte dans
un multi-ensemble toutes les valeurs ´mises pendant un instant. ∅ est le multi-ensemble vide
                                              e
et est l’union de multi-ensembles (si m1 = {v1 , ..., vn } et m2 = {v1 , ..., vk } alors m1 m2 =
{v1 , ..., vn , v1 , ..., vk }). Remarquons que dans l’implantation, les valeurs sont collect´es dans une
                                                                                             e
                                                                                    e e
liste et non dans un multi-ensemble. Cela permet d’avoir une syntaxe plus l´g`re pour le filtrage
                                               e
et d’utiliser les fonctions de la biblioth`que standard.
                              e   e       e
Le do/until sans r´cup´rateur d’´chappement n’applique pas un traitement particulier en cas
       e
de pr´emption.
                 `                                      u
Le let/in a une branche est un let/and/in o` la seconde branche ne calcule rien et termine
             e
instantan´ment.
             e                                                      `
    De mˆme, nous pouvons remarquer que le let/and/in a n branches se programme avec le
                                                                  e
let/and/in binaire. Les deux expressions suivantes sont ´quivalentes :
                                                                 let (x1 , x2 ) =
                         let x1 = e1                                let v1 = e1
                         and x2 = e2             def                and v2 = e2
                                                 =
                         and x3 = e3                                in (v1 , v2 )
                         in e                                    and x3 = e3
                                                                 in e
   Enfin, les autres constructions peuvent se programmer ainsi :
                                def
        nothing                 =     ()
                                def
        halt                    =     loop pause end
                                def
        await immediate s       =     do () when s
                                def
        await s                 =     await immediate s;pause
                                def
        await s(x) in e         =     do halt until s(x) -> e done
                                def
        e1 ||e2                 =     let x1 = e1 and x2 = e2 in ()
                                def
        loop e end              =     run ((rec loop = λx.process (run x;run (loop x))) e)
nothing est une construction de base d’Esterel. Elle est un synonyme pour la valeur () en
                      e
ReactiveML. L’ex´cution du processus halt ne termine jamais.
                                                     e
La construction await/immediate attend la pr´sence d’un signal. On la programme avec un
                                  e                          e                           e
do/when qui termine instantan´ment quand le signal est pr´sent. Il faut noter que la s´mantique
                              e                    e            e
de la version non instantan´e de await a une s´mantique diff´rente de celle de Esterel.
                             e     e                    e
Attendre un signal pour r´cup´rer la valeur associ´e peut se programmer avec un do/until.
                                          e               e e
Pour cela, le processus halt est utilis´. halt est ex´cut´ dans un do/until qui le pr´empte  e
             e                                         ee        e
quand s est ´mis. L’expression e dans laquelle x a ´t´ substitu´ par la valeur du signal est alors
  e e
ex´cut´e.
                        e                                  u       e   e
La composition parall`le se code avec un let/and/in o` on ne r´cup`re pas les valeurs calcul´es e
         e                                                 e
en parall`le. Le loop se programme par un processus r´cursif.
    Nous n’avons pas pris ici le noyau minimal du langage. Par exemple, les expressions suivantes
      e
sont ´quivalentes :
                           e1 ;e2 ≡ let x = e1 in e2 x ∈ f v(e)
                           pause ≡ signal x in present x else ()
     e                                  e
La s´quence se programme avec la d´pendance introduite dans le let/in. L’instruction pause
                                 e       `                                    e
peut utiliser le retard pour la r´action a l’absence. Comme x est absent, l’ex´cution de la branche
                                        `
else de l’instruction present a lieu a l’instant suivant.
48                                                            e
                                                          3. S´mantique comportementale




                                                    0    e                             1   e                          0       e
      k       x            k      c                                                                                                                1        pause
                                                k       λx.e               k       process e                    k         rec x = e

              0     e1           0        e2             0       e1        0    e2                     k        e1        k       e2       k       e
                   k           e 1 e2                        k        (e1 , e2 )               k       let x1 = e1 and x2 = e2 in e

              0        e1         0       e2             k       e1        k       e2                   0       e         1   e1        1      e2
              k        emit e1 e2                                k      e1 ;e2                 1       present e then e1 else e2

                           0         e1        0    e2       k         e                                    0        e1       1    e2          1       e3
          k       signal x default e1 gather e2 in e                                               1       do e2 until e1 (x) -> e3 done

                           0      e1        1       e2                     0       e                   0        e                      0       e
                       1        do e2 when e1                          k       pre e               k    pre ?e                     1       run e



                                                      e                                  e
                                          Fig. 3.2 – S´paration des expressions instantan´es


                          ee      e
   Ces constructions ont ´t´ gard´es dans le noyau afin donner une meilleure intuition pour
                               e        e
comprendre le formalisme des r`gles de s´mantique.
                         ee                                      e                       e
   Le await/one et les r´f´rences qui peuvent introduire de l’ind´terminisme seront trait´s
 e e
s´par´ment dans le chapitre 4.3.


3.2                                              e
          Identification des expressions instantan´es
             e                                 e              e
   Afin de s´parer clairement les expressions r´actives (ou s´quentielles en utilisant la termi-
                               e
nologie des circuits) dont l’ex´cution peut prendre plusieurs instants, des expressions instan-
   e                                                            e
tan´es (ou combinatoires), les expressions doivent suivre des r`gles de bonne formation. Cette
 e                                     ` e                  e                          `
s´paration discrimine les expressions a ´tat de celles sans ´tat. De plus, elle permet a la fois
                      e                    e
une plus grande clart´ des programmes et ´galement d’appliquer des techniques de compilation
   e                                                               e
diff´rentes pour les expressions combinatoires et les expressions s´quentielles. En particulier,
                                                  e e
nous voulons que les expressions Ocaml soient ex´cut´es sans surcoˆt.u

 e
D´finition 1 (Bonne formation)
Une expression e bien form´e doit v´rifier le pr´dicat k
                          e        e           e                                                        e d´fini figure 3.2 o` k ∈ {0, 1}.
                                                                                                           e               u
       e                                                           e          e
Ce pr´dicat se lit “dans un contexte k l’expression e est bien form´e”. 0 repr´sente le contexte
                           e                    e
des expressions instantan´es et 1 le contexte r´actif. Lorsque 0 e, alors e est une expression
           e                              e
instantan´e. Sinon e est une expression r´active.
                             e       e
    Dans la figure 3.2, une r`gle donn´e dans un contexte k (k e) est un raccourci pour les deux
 e                                                                                          e
r`gles 0 e et 1 e. Par exemple, cela signifie que les variables et les constantes peuvent ˆtre
      e                                                        e          e         e
utilis´es dans tous les contextes. Une abstraction (λx.e) peut ´galement ˆtre utilis´e dans tous
                                        e         `
                                  3.3. S´mantique a grands pas                                   49

                                           e             e            e           e
les contextes alors que son corps doit n´cessairement ˆtre instantan´. Pour la d´finition d’un
                                       e      e                                             e
processus (process e), le corps peut ˆtre r´actif. Toutes les expressions ML sont bien form´es
                                                                                    e
dans tous les contextes, mais les expressions comme pause, run ou present dont l’ex´cution peut
                                             e        e
se faire sur plusieurs instants ne peuvent ˆtre utilis´es que dans des processus. Nous pouvons
                        e                                                   e
remarquer qu’aucune r`gle ne permet de conclure qu’une expression est typ´e uniquement dans
                                                    e
un contexte 0 et pas dans un contexte 1. Par cons´quent, toutes les expressions combinatoires
          e        e
peuvent ˆtre utilis´es dans des processus.
Remarque :
             e
   Avec ces r`gles de bonne formation, nous avons fait des choix dans le design du langage.
                                                                                    e
   Par exemple pour la paire nous aurions pu autoriser l’utilisation d’expressions r´actives :

                                                 k       e1 k     e2
                                                     k    (e1 , e2 )

      Mais dans ce cas, le programme ((emit s; 1), (pause; 2)) a plusieurs s´mantiques   e
                              e                                         `                e
      possibles. Si l’ordre d’´valuation d’une paire est de gauche a droite, s est ´mis d`s le  e
                                             e                        `               e
      premier instant alors que si l’ordre d’´valuation est de droite a gauche, s est ´mis au second
                                                         e
      instant. Nous pouvons aussi faire le choix d’ex´cuter les deux expressions en parall`le.    e
                                                             e
      Nous trouvons plus naturel d’interdire ces possibilit´s dans une paire. Elles peuvent ˆtre e
              e            e                                  e                         ee
      exprim´es avec la s´quence et la composition parall`le. Par exemple, on pr´f´rera ´crire e
      (emit s || pause); (1, 2).
                                                                          e
      Cet exemple illustre un choix dans le design du langage qui doit ´viter autant que possible
          e
      les ´critures troublantes.


3.3      e         a
        S´mantique ` grands pas
        e                              e      e
    La s´mantique comportementale d´crit la r´action d’un programme comme une succession de
 e           u         e             e         e                            e
r´ductions o` chaque r´duction repr´sente l’ex´cution d’un instant. Cette s´mantique s’inspire
       e
de la s´mantique logique comportementale de Esterel [11].
        e            e                                                e
    La s´mantique int`gre la description du comportement des parties r´actives et combinatoires.
                                              e
Ceci permet d’obtenir une formalisation compl`te du langage en rendant explicite les interactions
                       `                                       e                      e
entre les deux mondes a travers un formalisme commun. Ce n’´tait pas le cas des s´mantiques
   e e              e e                  e
pr´c´dentes du mod`le r´actif, ni de la s´mantique comportementale de Esterel. De plus, c’est
         e   e           `                   e e
la premi`re s´mantique a grand pas du mod`le r´actif.

3.3.1    Environnement de signaux
         e                             e                 `
    La r´action d’un programme se d´finit par rapport a un ensemble de signaux. Dans cette
                                e                                           e
section, ces ensembles et les op´rations permettant de les manipuler sont d´finis formellement.
    Les noms de signaux sont not´s n et appartiennent a un ensemble d´nombrable N . Si N 1 ⊆ N
                                  e                   `              e
et N2 ⊆ N , nous notons N1 · N2 l’union de ces deux ensembles qui est d´finie uniquement si
                                                                           e
N1 ∩ N2 = ∅.

 e
D´finition 2 (Environnement de signaux)
Un environnement de signaux S est une fonction :

                       S ::= [(d1 , g1 , p1 , m1 )/n1 , ..., (dk , gk , pk , mk )/nk ]
50                                          e
                                        3. S´mantique comportementale

      `                                                                   u                      e
qui, a un nom de signal ni , associe un quadruplet (di , gi , pi , mi ) o` di est la valeur par d´faut
                                                                        e
de ni , gi est une fonction de combinaison, pi est une paire repr´sentant le statut du signal a      `
             e e                  e                                                 e
l’instant pr´c´dent et sa derni`re valeur et mi le multi-ensemble des valeurs ´mises pendant la
 e
r´action.
                                                                            e
    Si le signal ni est de type (τ1 , τ2 ) event alors les valeurs associ´es au signal ont les types
suivants :
                           d i : τ2                      pi : bool × τ2
                           g i : τ1 → τ 2 → τ 2          mi : τ2 multiset

     on note S d (ni ) = di , S g (ni ) = gi , S p (ni ) = pi et S v (ni ) = mi .
                                             e                   e
     On utilise des multi-ensembles pour repr´senter les valeurs ´mises pendant un instant car
                      e                                                        e
ils ne sont pas ordonn´s et permettent de garder plusieurs occurrences d’une mˆme valeur. Par
exemple, pour le programme :
emit s 1 || emit s 2 || emit s 1
le multi-ensemble des valeurs associ´es a s sera {1, 1, 2}.
                                    e `
                                        e                             e `
    Comme tous les signaux sont valu´s, si le multi-ensemble associ´ a un signal n dans un
environnement S est vide (S v (n) = ∅), cela signifie que n n’a pas ´t´ ´mis. On le note n ∈ S.
                                                                   eee
R´ciproquement, si S v (n) = ∅ alors n est pr´sent dans l’environnement S (not´ n ∈ S).
  e                                          e                                e

 e           ´ e
D´finition 3 (Ev´nement)
   e e
Un ´v´nement E est une fonction des noms de signaux dans les multi-ensembles de valeurs :

                                          E ::= [m1 /n1 , ..., mk /nk ]
        e e                  `      e                                            e
    Les ´v´nements servent a repr´senter des ensembles de valeurs qui sont ´mises sur des
signaux. S v est l’´v´nement associ´ a l’environnement S.
                   e e             e`
                       e e                    e               e e
    L’union de deux ´v´nements E1 et E2 d´finit un nouvel ´v´nement E = E1 E2 o` pour      u
                                          e                             e `
chaque signal n le multi-ensemble associ´ est l’union des valeurs associ´es a n dans E 1 et E2 :
                           ∀n ∈ Dom(E1 ) ∪ Dom(E2 ) : E(n) = E1 (n)                 E2 (n)
avec la convention que pour tout ´v´nement E, si n ∈ Dom(E) alors E(n) = ∅.
                                    e e
        e      c           e
De la mˆme fa¸on, nous d´finissons E = E1 E2 , l’intersection de E1 et E2 qui garde uniquement
                     `
les valeurs qui sont a la fois dans E1 et E2 :
                           ∀n ∈ Dom(E1 ) ∪ Dom(E2 ) : E(n) = E1 (n)                 E2 (n)
                                             e`
Ajouter une valeur v au multi-ensemble associ´ a un signal n dans un environnement de signaux
                   e
S se note avec l’op´rateur + :
                                           S(n )                                        si n = n
                 (S + [v/n])(n ) =
                                           (S d (n), S g (n), S p (n), S v (n)   {v})   si n = n
     e
On d´finit la relation d’ordre         e e                 e
                              sur les ´v´nements que l’on ´tend aux environnements de
signaux :
                       E1 E2 ssi ∀n ∈ Dom(E1 ) : E1 (n) ⊆ E2 (n)
                                    v
                       S1 S2 ssi S1 S2    v

     Enfin on notera ⊆, l’ordre sur les fonctions d´fini par :
                                                  e
                                 f1 ⊆ f2 ssi ∀x ∈ Dom(f1 ) : f1 (x) = f2 (x)
                                       e         `
                                 3.3. S´mantique a grands pas                                     51

3.3.2      e
          S´mantique
        e                                                                 e
    La r´action en un instant d’une expression e en une expression e est d´finie par une relation
de transition de la forme :
                                                 E, b
                                         N e −→ e−
                                                      S

 u
o`
                                                  ee         e
    – N est l’ensemble des noms de signaux cr´´s par la r´action.
                                                              e                                 e
    – S est l’environnement de signaux dans lequel e doit r´agir. Il contient les signaux d’entr´e,
      de sortie et les signaux locaux.
         e e                e                   e                 e
    – L’´v´nement E repr´sente les signaux ´mis pendant la r´action.
                                                             e
    – b est le statut de terminaison. C’est une valeur bool´enne indiquant si l’expression e doit
      e          e `                                      e     e
      ˆtre activ´e a l’instant suivant ou si elle a termin´ sa r´action.
         e                                                                        e
    L’ex´cution d’un programme est une succession potentiellement infinie de r´actions. Elle est
termin´e lorsque que le statut b est vrai. A
       e                                     ` chaque instant, un programme lit des entr´es (Ii )
                                                                                           e
   e                           e                          e
et ´met des sorties (Oi ). L’ex´cution d’un instant est d´finie par le plus petit environnement de
signaux Si (pour l’ordre ) tel que :

                                                     Ei , b
                                            Ni       −→
                                                 e i − − ei
                                                      Si

 u
o`
                                  (Ii Ei ) Si  v                (1)
                                  Oi = next(Si )                (2)
                                  ∀n ∈ Ni+1 . n ∈ Dom(Si )      (3)
                                    d   d        g   g
                                  Si ⊆ Si+1 et Si ⊆ Si+1        (4)
                                        p
                                  Oi ⊆ Si+1                     (5)
                        v                                e         e                 e
(1) L’environnement Si doit contenir les signaux d’entr´e et ceux ´mis pendant la r´action, cela
                  ee                         e     e e                                  `
garantit la propri´t´ de diffusion instantan´e des ´v´nements. (2) La sortie O i associe a chaque
                     e                                                              e
signal son statut (pr´sent/absent) et une valeur qui est la combinaison des valeurs ´mises. Donc
                                            e
la fonction next qui calcule la sortie est d´finie par :

                                           (false, v)         si n ∈ S et S p (n) = (b, v)
        ∀n ∈ Dom(S). next(S)(n) =
                                           (true, fold g m d) si n ∈ S et S(n) = (d, g, p, m)

avec fold tel que :
                           fold f ({v1 }    m) v2 = fold f m (f v1 v2 )
                           fold f ∅ v             = v
                 e `                                           e e
La sortie associ´e a un signal n est donc false et la valeur pr´c´dente de n, s’il est absent. Sinon,
                                           e
c’est true et la combinaison des valeurs ´mises pendant l’instant.
    (3) La condition ∀n ∈ Ni+1 .n ∈ Dom(Si ) garantit que les noms introduits lors de la r´action
                                                                                              e
                                             d ⊆ Sd        g      g
sont des noms frais. (4) Les conditions Si         i+1 et Si ⊆ Si+1 indiquent que les valeurs par
  e                                                            e                `
d´faut et les fonctions de combinaison des signaux sont gard´es d’un instant a l’autre. (5) Enfin,
        p
Oi ⊆ Si+1 est la transmission des valeurs des signaux pour le calcul du pre.
                      d     d      g     g
    Les contraintes Si ⊆ Si+1 et Si ⊆ Si+1 ont pour cons´quence de garder dans l’environnement
                                                           e
                    ee          e
tous les signaux cr´´s par la r´action du programme. Mais on peut remarquer que les signaux
                                                             e            e
de Si qui ne sont pas des variables libres dans ei peuvent ˆtre supprim´s de l’environnement de
signaux Si+1 .
52                                              e
                                            3. S´mantique comportementale



                                                             E1 , true                      E2 , true
                                                    N1       − −→
                                                         e 1 − − − v1          N2            − −→
                                                                                         e 2 − − − v2
                              ∅, true                           S                              S
                  ∅         −−
                          v −−→ v
                                  S                                         E1 E2 , true
                                                     N1 · N2                   −−−→
                                                                   (e1 , e2 ) − − − − (v1 , v2 )
                                                                                    S

                          E1 , true                         E2 , true                                   E3 , true
             N1       − −→
                   e1 − − − λx.e N2                          − −→
                                                         e 2 − − − v2          N3                  − −→
                                                                                        e[x ← v2 ] − − − v
                              S                                S                                             S
                                                                    E1 E2 E3 , true
                                        N1 · N2 · N3              −−−−−
                                                           e 1 e2 − − − − − → v
                                                                           S

                                          E, true                          E1 , true                         E2 , true
        N                      −−
             e[x ← rec x = e] − − → v                          N1           − −→
                                                                         e1 − − − n N 2                   − −→
                                                                                                       e2 − − − v
                                            S                                   S                                S

                                  E, true                                                  E1 E2 [{v}/n], true
            N                −−
                  rec x = e − − → v                        N1 · N2                   − − − − − −→
                                                                          emit e1 e2 − − − − − − − ()
                                      S                                                                  S

                      E, true                                                  E, true
             N    e − − → n (b, v) = S p (n)
                     −−                                              N     e − − → n (b, v) = S p (n)
                                                                              −−
                          S                                                         S
                                          E, true                                              E, true
                      N              −−
                              pre e − − → b                                 N               −−
                                                                                    pre ?e − − → v
                                             S                                                     S




                                            e
                                Fig. 3.3 – S´mantique comportementale (1)


                                        e                                   e
    La relation de transition est d´finie figure 3.3 en donnant les r`gles pour les expressions
           e
instantan´es (celles pour lesquelles 0 e).
                                                         e
    Nous pouvons remarquer que dans toutes les r`gles, le statut de terminaison b est vrai,
                         e                      e                                  e
montrant bien que l’ex´cution est instantan´e. Pour les expressions ML, les r`gles sont bas´es  e
        e                               `                                          e    e e
sur la s´mantique classique de ML a “grands pas”. Nous avons seulement ajout´ les ´v´nements
                                 e                                                   e
(E) pour pouvoir exprimer l’´mission de signaux dans les expressions instantan´es, les environ-
nements de signaux (S) pour pouvoir calculer les pre et les ensembles de noms frais (N ) pour
           e
pouvoir d´clarer de nouveaux signaux dans les parties instantan´es.    e
      e                   e
    D´taillons quelque r`gles de cette figure 3.3 :
                 e
    – Lors de l’´valuation d’une valeur aucun signal n’est ´mis.e
             e                     e                                   e
    – Pour ´valuer (e1 , e2 ), on ´value les deux branches dans le mˆme instant. Ces deux branches
        e                      e
       r´agissent dans le mˆme environnement de signaux S pour avoir une vision globale et
           e                         e
       coh´rente des signaux pr´sents pendant un instant. E1 et E2 sont les signaux ´mis pare
           e                                e                   e
       la r´action de e1 et e2 , donc la r´action de (e1 , e2 ) ´met l’union de E1 et E2 . Enfin, les
                  ee                e                  ee           e
       signaux cr´´s par cette r´action sont ceux cr´´s par la r´action de e 1 et e2 . Les noms de
       ces signaux sont pris dans N1 et N2 .
                                   e                                      e         e
    – L’expression emit e1 e2 ´value e1 en un signal n et ajoute le r´sultat de l’´valuation de e2
                                       e                   e
       dans l’ensemble des valeurs ´mises pendant la r´action.
               e                              e        e     e    e
    – Pour l’´valuation des pre, le param`tre doit ˆtre ´valu´ en un signal puis on va chercher
                                                                      e e
       dans l’environnement de signaux le statut ou la valeur pr´c´dente du signal.
                                        e                           e           e         e
    On commente maintenant les r`gles de la figure 3.4 qui pr´sentent les r`gles de s´mantique
             e
du noyau r´actif.
                                               e         `
                                         3.3. S´mantique a grands pas                                                                             53




                          E, true                                           E1 , b
               N1          −−
                        e − − → process e1                   N2              −→
                                                                         e 1 − − e1
                             S                                                S                                          ∅, false
                                                                                                     ∅             −−
                                                                                                             pause − − → ()
                                                        E E1 , b                                                              S
                           N1 · N2                  − −→
                                              run e − − − e1
                                                             S

                                 E1 , false                                        E1 , true                              E2 , b
                    N          − −→
                           e 1 − − − e1                              N1         − −→
                                                                            e 1 − − − e1                     N2       e 2 − − e2
                                                                                                                          −→
                                     S                                                 S                                    S
                                 E1 , false                                                                  E1 E2 , b
               N            − −→
                     e1 ;e2 − − − e1 ;e2                                   N1 · N2                  −−→
                                                                                            e1 ;e2 − − − e2
                                     S                                                                            S

                                         E1 , b 1                          E2 , b 2
                          N1             −→
                                    e 1 − − e1              N2            −→
                                                                     e 2 − − e2                b1 ∧ b2 = false
                                              S                               S
                                                                         E1 E2 , false
      N1 · N2                                      −−−→
                     let x1 = e1 and x2 = e2 in e − − − − let x1 = e1 and x2 = e2 in e
                                                                               S

                        E1 , true                           E2 , true                                                              E, b
         N1             − −→
                    e 1 − − − v1              N2         − −→
                                                     e 2 − − − v2                 N3       e[x1 ← v1 , x2 ← v2 ] − → e
                                                                                                                  −
                           S                                     S                                                                  S
                                                                                                     E1 E2 E, b
                        N1 · N2 · N3                                            −−−→
                                                  let x1 = e1 and x2 = e2 in e − − − − e
                                                                                                              S

        E1 , true                        E2 , true                                                                                         E, b
N1       − −→
     e 1 − − − v1          N2           − −→
                                    e 2 − − − v2                 S(n) = (v1 , v2 , (false, v1 ), m)                     N3                   −
                                                                                                                                   e[x ← n] − → e
           S                                  S                                                                                             S
                                                                                                                      E1 E2 E, b
           N1 · N2 · N3 · {n}                                                     −−−→
                                              signal x default e1 gather e2 in e − − − − e
                                                                                                                          S

                                                  E, true                                       E1 , b
                                    N1          −−
                                              e −−→ n n ∈ S                       N2           −→
                                                                                           e 1 − − e1
                                                    S                                             S
                                                                                                 E E1 , b
                               N1 · N2                                      − −→
                                                  present e then e1 else e2 − − − e1
                                                                                                         S

                                                                 E, true
                                                    N         −−
                                                            e −−→ n n ∈ S
                                                                     S
                                                                                            E, false
                                    N                                −−
                                          present e then e1 else e2 − − → e2
                                                                                                 S




                                             e
                                 Fig. 3.4 – S´mantique comportementale (2)
54                                    e
                                  3. S´mantique comportementale

                e                 e                             e
     – run e ´value e en une d´finition de processus et l’ex´cute.
                     e                                             e    `
     – pause se r´duit en (). Son statut de terminaison est ´gal a false pour marquer l’attente
       de la fin de l’instant.
              e               e
     – Les r`gles pour la s´quence illustrent l’utilisation du statut de terminaison b. L’expression
                  e e
       e2 est ex´cut´e seulement si e1 termine dans l’instant (b = true).
                                                     e                        e
     – Le comportement du let/and/in est d’ex´cuter e1 et e2 en parall`le. Quand ces expres-
                       e                                                            e
       sions sont r´duites en des valeurs v1 et v2 , alors x1 et x2 sont substitu´s respectivement
       par v1 et v2 dans e.
                                                 e
     – signal x default e1 gather e2 in e d´clare un nouveau signal x. La valeur par d´faut     e
                                                          e    e                        e
       (e1 ) et la fonction de combinaison (e2 ) sont ´valu´es au moment de la d´claration. Le
                             e
       nom x est substitu´ par un nom frais n dans e. Dans l’environnement des signaux, le pre
                                e                                               e
       du signal est initialis´ avec le statut absent et avec la valeur par d´faut. Pour le multi-
                                  e                                  e        e
       ensemble m, les valeurs ´mises pendant l’instant doivent ˆtre devin´es. Cela veut dire que
            e                 e                        e                                     e
       la d´rivation compl`te du programme doit v´rifier que m contient bien les valeurs ´mises
       pendant l’instant.
                            e                                      e                          e e
     – Dans le test de pr´sence d’un signal, si le signal est pr´sent, la branche then est ex´cut´e
                   e
       instantan´ment. Sinon, comme le statut de terminaison est b = false, la branche else est
          e e `
       ex´cut´e a l’instant suivant.
                       e          e                                               e
     Enfin, nous pr´sentons la s´mantique des instructions de suspension et pr´emption figure 3.5.
                         e                                                            o
     – Le do/when ex´cute son corps uniquement quand le signal qui le contrˆle est pr´sent.    e
                                                         e
       Quand le corps est actif et termine son ex´cution, le do/when termine aussi instan-
           e                        e     e                       `         e
       tan´ment. Dans chaque r`gle on ´value le signal mais a la premi`re activation l’expression
               e     e
       e est ´valu´e en une valeur n. Donc pour les activations aux instants suivant le do/when
                              oe        e
       sera toujours contrˆl´ par le mˆme signal n.
     – Enfin, le do/until active toujours son corps. Si le corps termine, le do/until se r´´critee
                                                 e                e    e                  e
       en la valeur de son corps. En cas de pr´emption, il r´cup`re la valeur associ´e au signal
                          e                                  e            `
       pour pouvoir ex´cuter le code de traitement de pr´emption a la prochaine activation.
Remarque :
                            e                     e e
   L’ensemble N est utilis´ comme comme g´n´rateur de noms frais. Pour simplifier la
     e                                 e             e              e
   pr´sentation l’ensemble N pourrait ˆtre supprim´ de toutes les r`gles et la fonction gensym
        e e                                     e           e                              e
   qui g´n`re des noms frais serait alors utilis´e dans la r`gle de signal/in. Ainsi les r`gles
                          e            e
   auraient la forme des r`gles de la s´mantique comportementale de Esterel :

                                                   E, b
                                                    −
                                                  e −→ e
                                                       S


                                           e                 e                         e
   Nous terminons cette description de la s´mantique par la d´finition de la relation d’´quivalence
entre deux expressions.

 e             ´
D´finition 4 (Equivalence)
                               e
Deux expressions e1 et e2 sont ´quivalentes si pour tout environnement de signaux S tel que

                                       E1 , b 1                   E2 , b 2
                            N1         −→
                                  e 1 − − e1      et       N2        −→
                                                                e 2 − − e2
                                          S                          S

alors E1 = E2 , b1 = b2 et e1 = e2 .
                                    e         `
                              3.3. S´mantique a grands pas                                                         55




                                                   E, true
                                      N          −−
                                               e −−→ n n ∈ S
                                                        S
                                                            E, false
                          N                   −−
                                do e1 when e − − → do e1 when n
                                                               S

                                E, true                                        E1 , false
                      N         −−
                              e −−→ n n ∈ S                        N1          − −→
                                                                           e 1 − − − e1
                                  S                                                     S
                                                            E E1 , false
                   N · N1                     − − −→
                                 do e1 when e − − − − do e1 when n
                                                                   S

                                E, true                                            E1 , true
                      N         −−
                              e −−→ n n ∈ S                        N1         − −→
                                                                           e1 − − − v
                                     S                                                  S
                                                                       E E1 , true
                              N · N1                     − − −→
                                            do e1 when e − − − − v
                                                                           S

                                         E, true                          E1 , true
                            N         −−
                                   e − − → n N1                           − −→
                                                                       e1 − − − v
                                           S                                   S
                                                                                    E E1 , true
                 N · N1                                    − − −→
                               do e1 until e(x) -> e2 done − − − − v
                                                                                            S

     E, true                                   E1 , false
N     −−
    e −−→ n n ∈ S               N1            − −→
                                          e 1 − − − e1                 S(n) = (d, g, p, m)        v = fold g m d
         S                                          S
                                                                           E E1 , false
             N · N1                                   − − −→
                          do e1 until e(x) -> e2 done − − − − e2 [x ← v]
                                                                                    S

                                E, true                                        E1 , false
                      N         −−
                              e −−→ n n ∈ S                        N1          − −→
                                                                           e 1 − − − e1
                                  S                                                     S
                                                            E E1 , false
N · N1                                   − − −→
             do e1 until e(x) -> e2 done − − − − do e1 until n(x) -> e2 done
                                                                   S




                                  e
                      Fig. 3.5 – S´mantique comportementale (3)
56                                                  e
                                                3. S´mantique comportementale

3.3.3                   e
           Exemples de d´rivations
 e                          e e
S´mantique des expressions d´riv´es
    `               e                                                   e
    A partir de la s´mantique des expressions du noyau du langage, les r`gles pour les expressions
 e e               e
d´riv´es peuvent ˆtre construites.
                               e                    c
    Section 3.1.2, nous avons d´fini e1 ||e2 de la fa¸on suivante : let x1 = e1 and x2 = e2 in ().
      e
Les d´rivations possibles pour cette expression sont :
                                             E1 , b 1                      E2 , b 2
                          N1              −→
                                     e 1 − − e1             N2           −→
                                                                    e 2 − − e2             b1 ∧ b2 = false
                                                S                             S
                                                                       E1 E2 , false
         N1 · N2                                  −−−→
                   let x1 = e1 and x2 = e2 in () − − − − let x1 = e1 and x2 = e2 in ()
                                                                                 S

et
                                      E1 , true                        E2 , true                              ∅, true
                       N1            − −→
                                 e 1 − − − v1               N2     e 2 − − − v2
                                                                       − −→                    ∅          −−
                                                                                                       () − − → ()
                                         S                                   S                                  S
                                                                                                   E1 E2 , true
                        N1 · N2                                             −−−→
                                             let x1 = e1 and x2 = e2 in () − − − − ()
                                                                                                          S
                              e      e                                e
   Donc la composition parall`le ex´cute e1 et e2 et termine instantan´ment quand les deux
                   e        e
branches ont termin´ leur ex´cution.
                                       e                                e
   L’expression await immediate e est d´finie par : do () when e. Si e s’´value en un signal n,
          e
on a les d´rivations suivantes :
                       E, true                                                         E, true                                        ∅, true
              N      −−
                   e −−→ n n ∈ S                                            N           −−
                                                                                      e −−→ n n ∈ S                        ∅          −−
                                                                                                                                   () − − → ()
                         S                                                                 S                                            S
                             E, false                                                                                      E, true
     N                   −−
           do () when e − − → do () when n                                             N                      −−
                                                                                                do () when e − − → ()
                                 S                                                                                             S

          e
Donc les r`gles pour await/immediate sont :
                             E, true                                                                                    E, true
                   N       −−
                         e −−→ n n ∈ S                                                                    N           −−
                                                                                                                    e −−→ n n ∈ S
                                 S                                                                                         S
                                     E, false                                                                                             E, false
 N                          −−
         await immediate e − − → await immediate n                                             N                          −−
                                                                                                       await immediate e − − → ()
                                         S                                                                                                      S

         e             e        e
     De mˆme, on peut v´rifier l’´quivalence entre pause et l’expression suivante :
                                     signal x in present x then () else ()
    e
La d´rivation de cette expression est :
                                                                 ∅, true
                                                        N      −−
                                                             n −−→ n n ∈ S
                                                                   S

                                                                                               ∅, false
                                     N                                  −−
                                              present n then () else () − − → ()
                                                                                                   S

                                                                                                                ∅, false
                   N · {n}                                                 −−
                                     signal x in present x then () else () − − → ()
                                                                                                                    S

                         e                  e
Comme n ne peut pas ´chapper de sa port´e dans present n then () else (), on peut faire
l’hypoth`se S
        e     v (n) = ∅ et donc n ∈ S. Ceci donne la r`gle attendue pour pause :
                                                      e
                                                                           ∅, false
                                                        N          −−
                                                             pause − − → ()
                                                                              S
                                             e         `
                                       3.3. S´mantique a grands pas                                                       57

                             e
Exemple de dialogue instantan´
                                   e                                          c
   Nous illustrons maintenant la s´mantique sur des petits exemples. Commen¸ons avec un
                             e                          e
exemple de composition parall`le avec dialogue instantan´ entre les branches.
                 (emit n1 ;present n2 then emit n3 )||(present n1 then emit n2 )
                                      e              e        e
Dans cet exemple, la branche gauche ´met n1 qui d´clenche l’´mission de n2 dans la branche
                        e              e    e
droite. Comme n2 est pr´sent, n3 peut ˆtre ´mis par la branche gauche.
    ´           e                                                     e
   Ecrivons la d´rivation de cette expression dans l’environnement S d´fini comme suit :
                       ∀i ∈ {1, 2, 3} S d (ni )        =    ()
                                      S g (ni )        =    λx.λy.()
                                      S p (ni )        =    (false, ∅)
                       et             Sv               =    [{()}/n1 ; {()}/n2 ; {()}/n3 ]

                                                  D1                D2
                                                                                                                E, true
       ∅                                                                       −−
              (emit n1 ;present n2 then emit n3 )||(present n1 then emit n2 ) − − → ()
                                                                                                                  S

avec E = [{()}/n1 ; {()}/n2 ; {()}/n3 ]
   D1 :
                                                                                             [{()}/n3 ], true
                                                           n2 ∈ S    ∅               − − − −→
                                                                             emit n3 − − − − − ()
                                                                                                    S
                        [{()}/n1 ], true                                                           [{()}/n3 ], true
          ∅           − − − −→
              emit n1 − − − − − ()                ∅                            − − − −→
                                                       present n2 then emit n3 − − − − − ()
                                 S                                                                        S

                                                                          [{()}/n1 ;{()}/n3 ], true
                   ∅                                     −−−−−−−
                       emit n1 ;present n2 then emit n3 − − − − − − − → ()
                                                                                         S

   D2 :
                                                                [{()}/n2 ], true
                                     n1 ∈ S   ∅            − − − −→
                                                   emit n2 − − − − − ()
                                                                         S

                                                                         [{()}/n1 ], true
                             ∅                               − − − −→
                                     present n1 then emit n2 − − − − − ()
                                                                                S
Nous observons dans cet exemple que la propri´t´ de diffusion (E ∈ S v ) oblige a avoir n1 , n2 et
                                             ee                                `
     e                                                                        e
n3 pr´sents dans l’environnement et donc permet la communication instantan´e entre les deux
branches.

                   e    e
Illustration du mod`le r´actif
                                                e
    Regardons maintenant le comportement de la s´mantique sur deux exemples qui ne sont pas
causaux en Esterel. Le premier n’est pas causal en Esterel car on ne peut pas lui donner
    e
de s´mantique.
                              present n then () else emit n
                               e      `                e            e
En ReactiveML, comme la r´action a l’absence est retard´e, on a la d´rivation suivante si on
                                         e
suppose qu’il n’y a pas de signaux d’entr´e :
                                                       n∈S
                                                                              ∅, false
                         ∅                                     −−
                                 present n then () else emit n − − → emit n
                                                                                    S
58                                         e
                                       3. S´mantique comportementale

                                                                                e
     Le second exemple n’est pas causal en Esterel car on peut lui donner deux s´mantique.

                                      present n then emit n else ()

                                  e
Ici aussi, en fonction des hypoth`ses faites sur l’environnement des signaux, on peut obtenir
       e             e
deux d´rivations diff´rentes. Si on suppose n absent de l’environnement S1 , on a :

                                                   n ∈ S1
                                                                             ∅, false
                            ∅                                     −−
                                    present n then emit n else () − − → ()
                                                                               S1

                             e
Et si on suppose que n est pr´sent dans S2 :
                                                            [{()}/n], true
                                     n ∈ S2   ∅           −−−−
                                                  emit n − − − − → ()
                                                                 S2

                                                                       [{()}/n], true
                      ∅                                        −−−−
                                present n then emit n else () − − − − → ()
                                                                               S2

           e                                           `                                    e
Ces deux d´rivations sont valides. Mais contrairement a Esterel, il y a une contrainte suppl´-
               e                   e
mentaire : la s´mantique est donn´e par le plus petit environnement dans lequel le programme
      e                                          e        e                      e
peut r´agir. On sait donc que si n n’est pas donn´ en entr´e, alors il n’est pas ´mis.

3.3.4                          e                e
         Discussion sur les diff´rences avec la s´mantique d’Esterel
         e       e         e
    L’id´e de d´crire la r´action du programme dans un environnement qui contient toute l’in-
                                      e   e                e                          e
formation sur les signaux qui vont ˆtre ´mis pendant la r´action est reprise de la s´mantique
                                                              e
logique comportementale d’Esterel [11]. Pour adapter la s´mantique d’Esterel au mod`le        e
 e                       u                          `                                 e
r´actif, nous avons dˆ ajouter du retard au test a l’absence, mais nous avons fait ´galement
                                                        e
des modifications plus profondes. La principale difficult´ vient du traitement des signaux valu´s e
               e
alors que la s´mantique d’Esterel ne traite que les signaux purs.
              e         e                              e
    La premi`re cons´quence de cet ajout concerne la d´finition des environnements de signaux.
                                 `                              e
Notre environnement S associe a chaque signal une valeur par d´faut, une fonction de combinai-
                   e e                                               e                e
son, la valeur pr´c´dente du signal et le multi-ensemble des valeurs ´mises. Dans la s´mantique
de Esterel, comme il n’y a que des signaux purs, l’environnement des signaux peut ˆtre      e
    e      e                                           e
repr´sent´ simplement comme l’ensemble des signaux ´mis.
                       e                    e                                           `
    La seconde cons´quence concerne la d´finition des signaux locaux. Contrairement a Este-
                                                                       e   e
rel, des signaux (ou des processus avec des signaux libres) peuvent ˆtre ´mis sur les signaux.
                        `      e    e       e                    e
Ceci peut conduire a des ph´nom`nes d’´chappement de port´e. Nous ne pouvons donc pas
            e                                   e
avoir les r`gles d’Esterel suivantes pour la d´claration de signaux :
                     E, b                                                     E, b
                   e−→e
                    −                s∈E                                    −
                                                                         e −→ e             s∈E
                     S+s                                                      S\s

                            E\s, b                                                   E, b
                         −→
          signal s in e − − signal s in e                                   −
                                                             signal s in e − → signal s in e
                                S                                                       S

                                                                                e
En effet, celles-ci ne permettent pas d’utiliser le signal s en dehors de sa port´e car il n’est pas
 e
d´fini dans l’environnement S.
             e                   e         e                  e     ee
   La premi`re solution propos´e pour r´soudre ce probl`me a ´t´ de donner la s´mantiquee
                        e                                                e          e
modulo une relation d’´quivalence comme pour le π-calcul [75]. L’id´e est de d´finir la com-
         e                                                              e     e
mutativit´ de signal avec les autres constructions et d’ajouter une r`gle d’´quivalence dans la
                                                e                    e
                                          3.4. D´terminisme et unicit´                                         59

 e                                                                          e
s´mantique. Par exemple signal commute avec do/when ou la composition parall`le mais ne
commute pas avec loop :
                 do signal s in e1 when e ≡ signal s in do e1 when e                         si s ∈ f v(e)
                 e1 ||signal s in e2      ≡ signal s in e1 ||e2                              si s ∈ f v(e1 )
                                          ...
    e      e                e           e
La r`gle d’´quivalence ajout´e dans la s´mantique est la suivante :
                                                            E, b
                                             e1 ≡ e 2        −
                                                         e2 − → e2    e2 ≡ e 1
                                                             S
                                                            E, b
                                                             −
                                                         e1 − → e1
                                                             S

                                                e                                   e
Cette approche permet de faire remonter la d´claration du signal aussi haut que n´cessaire.
                  eee                                                e
    Nous avons pr´f´r´ une solution plus simple qui s’inspire de la s´mantique des langages avec
 ee             e                                                                       e
r´f´rences. L’id´e est de rendre l’environnement S global. Ainsi, il n’y a plus de probl`mes de
     e                                                 e               e
port´e car tous les signaux sont accessibles. Afin d’´viter les probl`mes de collision entre les
                                                   e                     e
noms de signaux, un nom unique leur est attribu´ au moment de leur d´claration.
                      e           e                       `
    Enfin, l’originalit´ de notre s´mantique par rapport a celle de Esterel est de prendre en
           `                 e
compte a la fois la partie r´active et la partie combinatoire.
                    e     e                e                                        ee e
    Une variation tr`s int´ressante de la s´mantique comportementale d’Esterel a ´t´ pr´sent´ee
                                      e              e                          e
dans [102]. Elle permet de rendre d´terministe la s´mantique d’Esterel. L’id´e principale de
         e                  e                         e                                 e
cette s´mantique est d’int´grer l’analyse de causalit´ et la contrainte E S dans les r`gles de
                   e e         e                                                            e
signal. Ceci est r´alis´ en d´rivant le corps de signal s in e en faisant les deux hypoth`ses
       e                                                         e                    e
“s pr´sent” et “s absent”. En fonction des signaux qui sont ´mis par ces deux d´rivations,
    e                 e                 e                      e
la r`gle de signal d´termine quelle ´tait la bonne hypoth`se. S’il n’y avait pas le probl`mee
  e                      e
d’´chappement de port´e en ReactiveML, nous aurions pu utiliser une approche similaire.
      e
Les r`gles auraient la forme suivante :
      E − , b−                        E + , b+                                    E − , b−
  e − − → e−
     −−               s ∈ E−     e − − → e+
                                    −−                  s ∈ E+                   e − − → e−
                                                                                    −−               s ∈ E−
       S\s                             S+s                                          S\s

                         E + \s, b+                                                       E − , b−
      signal s in e − − − signal s in e+
                     −−→                                              signal s in e − − → signal s in e−
                                                                                     −−
                             S                                                               S

     e                             e                                                   e
Ces r`gles expriment que l’hypoth`se “s est absent” est plus prioritaire que “s est pr´sent”.
          e          e           e        e                             e
L’hypoth`se “s est pr´sent” est s´lectionn´e uniquement lorsque l’hypoth`se “s est absent” est
fausse (s ∈ E − ).


3.4        e                    e
          D´terminisme et unicit´
             e                              ee                      e
    Nous pr´sentons maintenant les propri´t´s principales de la s´mantique comportementale.
          e           e                                                      e
La premi`re est le d´terminisme : dans un environnement de signaux donn´, un programme ne
       e                        c                      ee                               e
peut r´agir que d’une seule fa¸on. La seconde propri´t´ que nous nommons unicit´ dit que si
                      e
un programme est r´actif, alors il existe un unique plus petit environnement de signaux dans
                e                         e            e          e
lequel il peut r´agir. Nous reprenons la d´finition de r´actif donn´e dans [11] : il existe au moins
                                                             E, b
un environnement de signaux S tel que N                      −
                                                           e −→ e .
                                                                 S
                                        ee                                     e
    La combinaison de ces deux propri´t´s garantit que tous les programmes r´actifs sont cor-
                   ee
rects. Cette propri´t´ n’est pas vraie en Esterel. Elle montre qu’il n’y a pas besoin d’analyse
           e
de causalit´ en ReactiveML, i.e, tous les programmes sont causaux.
60                                            e
                                          3. S´mantique comportementale

        e e     e
Propri´t´ 1 (D´terminisme)
                             e                                   e             `
Pour toute expression e, la s´mantique comportementale est d´terministe. C’est a dire :
∀e, ∀S, ∀N.
si ∀n ∈ Dom(S). S g (n) = f et f (x, f (y, z)) = f (y, f (x, z))
           E1 , b 1                E2 , b 2
et N       −→
        e − − e1 et N         −→
                           e − − e2
              S                       S
alors (E1 = E2 ∧ b1 = b2 ∧ e1 = e2 )

 e
D´monstration :
              e                             e
   Nous ne pr´sentons que le cas le plus int´ressant de la preuve.
                                                e
   Cas do e1 until e(x) -> e2 done avec pr´emption : Supposons que l’on ait les deux
    e
   d´rivations suivantes :
                                              E1 , true                               E1 , true
                               N         − −→
                                       e − − − n1          n1 ∈ S      N1               −1 − →
                                                                                   e 1 − − − e1 1
                                                 S                                        S
                                   S(n1 ) = (d1 , g1 , p1 , m1 ) v1 = fold g1 m1 d1
                                                                              E1 E1 , false
                      N · N1                                    − −1 −
                                                                    −
                                   do e1 until e(x) -> e2 done − − − − → e2 [x ← v1 ]
                                                                                      S


                                              E2 , true                               E1 , true
                               N         − −→
                                       e − − − n2          n2 ∈ S      N1               −2 − →
                                                                                   e 1 − − − e1 2
                                                 S                                        S
                                   S(n2 ) = (d2 , g2 , p2 , m2 ) v2 = fold g2 m2 d2
                                                                              E2 E1 , false
                      N · N1                                    − −2 −
                                                                    −
                                   do e1 until e(x) -> e2 done − − − − → e2 [x ← v2 ]
                                                                                      S

                                                        e
       Par induction on a E1 = E2 et n1 = n2 et ´galement E11 = E12 et e11 = e12 donc
                                                     ee                e                   e
       S(n1 ) = S(n2 ) = (d, g, p, m). Avec la propri´t´ d’associativit´ et de commutativit´ de la
                                                  u                  e
       fonction de combinaison g, nous sommes sˆrs que fold est d´terministe, donc v 1 = v2 . Par
       cons´quence, E1 E11 = E2 E12 et e2 [x ← v1 ] = e2 [x ← v2 ].
           e
                   e                    e
     L’associativit´ et la commutativit´ des fonctions de combinaison expriment le fait qu’elles
                   e                      e
ne doivent pas d´pendre de l’ordre des ´missions pendant l’instant. C’est une contrainte assez
              e                                                  e     e
forte mais mˆme si elle n’est pas satisfaite le programme peut ˆtre d´terministe. Par exemple,
                          e                                            `e
s’il n’y a pas de multi-´mission, la fonction de combinaison n’a pas a ˆtre associative et com-
                                                                          e
mutative. Ou si la fonction de combinaison construit la liste des valeurs ´mises et que toutes les
   e                                  e                            ee
op´rations faites sur cette liste ne d´pendent pas de l’ordre des ´l´ments, alors le programme
        e
reste d´terministe.
                                      ee          e
     Nous donnons maintenant la propri´t´ d’unicit´.

       e e
Propri´t´ 2 (Unicit´)e
Pour toute expression e, soit S l’ensemble des environnements de signaux tel que

                                                                            E, b
                                      S=           S | ∃N, E, b. N       −
                                                                       e −→ e
                                                                             S


alors il existe un unique plus petit environnement ( S) tel que

                                                                     E, b
                                                  ∃N, E, b. N      −
                                                                e −→ e
                                                                      S
                                            e                    e
                                      3.4. D´terminisme et unicit´                                            61

 e
D´monstration :
                              ee       e
   La preuve de cette propri´t´ est bas´e sur le lemme suivant qui dit que si un programme
           e                                               e                      e
   peut r´agir dans deux environnements de signaux diff´rents, alors il peut r´agir dans
   l’intersection de ces deux environnements.
                           e
   De plus, (S, , , ) d´finit un treillis avec un minimum. Donc l’intersection de tous les
                                                    e
   environnements dans lesquels l’expression peut r´agir est unique.
                              e                  e                e `             e e
    Le lemme suivant est bas´ sur l’absence de r´action instantan´e a l’absence d’´v´nement.
            e                e                                                         e e
Cette caract´ristique de la s´mantique garantit que l’absence d’un signal ne peut pas g´n´rer
    e
des ´missions.
Remarque :
                                                           e                     e
   On peut constater sur l’exemple suivant que cette caract´ristique n’est pas pr´sente en
   Esterel.
                             present n1 then () else emit n2
                                                e                              e e
     En Esterel, l’absence de n1 provoque l’´mission de n2 alors qu’avec le mod`le r´actif, si
                               e
     n1 est absent, rien n’est ´mis dans l’instant.

Lemme 1
                                                                                 e
Pour toute expression e, soit S1 et S2 deux environnements dans lesquels e peut r´agir :

                                          E1 , b 1                 E2 , b 2
                                 N1       −→
                                       e − − e1            N2      −→
                                                                e − − e2
                                            S1                        S2

                 v    v
Soit S3 tel que S3 = S1         v
                               S2 . Alors il existe E3 , b3 et e3 tels que
            E3 , b 3
    N3       −→
          e − − e3        et     b3 ⇒ (b1 ∧ b2 )      et   E3   (E1        E2 )        et   N3 ⊆ (N1 ∩ N2 )
              S3

 e
D´monstration :
                                            e                e
   La preuve se fait par induction sur les d´rivations. On pr´sente ici seulement le cas de
   present.
                                                    e
     Cas present e then e1 else e2 : dans les deux r`gles de present, on commence par
     e
     ´valuer l’expression e. Par induction, on a :
                                        Ei , true
          ∀i ∈ {1, 2, 3} : Ni          −−
                                      e−−→n           et   E3   (E1        E2 )        et   N3 ⊆ (N1 ∩ N2 )
                                           Si

                                 e                                       e
     On regarde maintenant les d´rivations possibles en fonction de la pr´sence de n dans S 3 :
     – Cas n ∈ S3 : par d´finition de S3 , n ∈ S3 ⇒ (n ∈ S1 ∧ n ∈ S2 ). Donc
                         e

                                          E1 , true                            E1 , b 1
                                N1     e − − − n n ∈ S1
                                         − −→                   N11             −1 −
                                                                           e 1 − − → e1 1
                                             S1                                   S1

                                                                              E1 E1 , b 1
                           N1 · N11        present e then e1 else e2 − − −1 − e11
                                                                     − − −→
                                                                                  S1

                                          E2 , true                            E1 , b 2
                                N2       − −→
                                       e − − − n n ∈ S2         N12             −2 −
                                                                           e 1 − − → e1 2
                                             S2                                   S2

                                                                              E2 E1 , b 2
                           N2 · N12        present e then e1 else e2 − − −2 − e12
                                                                     − − −→
                                                                                  S2
62                                          e
                                        3. S´mantique comportementale

                                   e
         Par induction et avec la r`gle de present :

                                              E3 , true                                           E1 , b 3
                                 N3         − −→
                                          e − − − n n ∈ S3                         N13             −3 −
                                                                                              e 1 − − → e1 3
                                                 S3                                                  S3

                                                                                                E3 E1 , b 3
                               N3 · N13       present e then e1 else e2 − − −3 − e13
                                                                        − − −→
                                                                                                       S3


                   et     b3 ⇒ (b1 ∧ b2 )             et        E 13        E 11       E 12     et        N13 ⊆ (N11 ∩ N12 )

                         e
         Avec ces hypoth`ses, nous pouvons montrer que (E3                                     E 13 )        (E1   E 11 )   (E2   E 22 )
         et que N3 · N13 ⊆ (N1 · N11 ∩ N2 · N12 )
       – Cas n ∈ S3 : dans ce cas, l’expression peut r´agir :
                                                      e

                                                                    E3 , true
                                                   N3             − −→
                                                                e −− − n n ∈ S
                                                                        S
                                                                                               E3 , false
                                   N3                                − −→
                                           present e then e1 else e2 − − − e2
                                                                                                   S

         et on peut montrer trivialement que false ⇒ (b1 ∧b2 ) et E3                                    (E1 E2 ) et N3 ⊆ (N1 ∩N2 )



3.4.1          e e
         Propri´t´s des expressions combinatoires
                                                                    e            e
    Nous terminons avec deux remarques sur les expressions instantan´es. La premi`re est la
                                   e e
correction de l’analyse d’instantan´it´.

       e e
Propri´t´ 3
                                 e
Pour toute expression e instantan´e (0                    e) et pour tout environnement S tel que l’expression
                        E, b
e peut r´agir (N
        e              −
                    e − → e ), alors la r´action de e termine instantan´ment (b = true)
                                         e                             e
                         S

                                                                                E, b
                ∀e, S        tels que     0      e         et       N       e −→ e
                                                                              −                alors         b = true
                                                                                   S

 e
D´monstration :
          e                                                        e            e
   Cette d´monstration est directe par induction sur le nombre de r`gles de la r´action.
     L’autre remarque est que pour toute expression e, pour tout environnement S tel que l’ex-
                                                           E, true
pression e termine instantan´ment (N
                            e                            −−
                                                      e − − → e ) alors e est une valeur.
                                                                S



3.5      Conclusion
           e                                        e    e                            e
    Cette s´mantique comportementale est la premi`re s´mantique que nous avons d´finie pour
                          e                e          e           `
ReactiveML. Il est int´ressant d’avoir d´fini une s´mantique a grands pas. Cela permet de
 e         e                                                                `     e
d´finir la r´action d’un instant sans prendre en compte l’ordonnancement a l’int´rieur de l’ins-
                                                       e                      e        e
tant. Ainsi c’est un bon formalisme pour prouver le d´terminisme et l’unicit´ de la r´action.
                        e                             e                             e
    En revanche, cette s´mantique ne permet pas de d´crire comment construire la r´action d’un
                                       e         e              ee                    e
instant. De plus, nous ne pouvons pas d´finir la s´mantique des r´f´rences dans cette s´mantique.
                                        3.5. Conclusion                                           63

 e   e
R´sum´
                                      e                                             e
    Ce chapitre commence par la pr´sentation du noyau du langage avec une premi`re analyse
                                                  e                  e               e
permettant d’identifier les expressions dont l’ex´cution est instantan´e. Puis, une s´mantique
`                               e     e           e                                    ee
a grands pas du noyau est pr´sent´e et illustr´e sur des exemples. Enfin, les propri´t´s de
  e                      e            e              e      e
d´terminisme et d’unicit´ de cette s´mantique sont d´montr´es.
           e                          e                                           e
    Cette s´mantique s’inspire de la s´mantique comportementale de Esterel. L’ex´cution d’un
             e
instant est d´finie par une relation de la forme :
                                                   E, b
                                           N      −
                                                e −→ e
                                                    S

                e          e                                ıtre                     e e
La particularit´ de cette s´mantique est qu’il faut connaˆ les signaux qui vont ˆtre ´mis par la
 e                               e               e          e                             e
r´action de e avant de faire la d´rivation : la d´rivation v´rifie seulement que les hypoth`ses faites
                                                          e
sur l’environnement ne sont pas fausses. Ainsi cette s´mantique s’abstrait de l’ordonnancement
                                                                               e
intra-instant. En contrepartie de ce haut niveau d’abstraction, un interpr`te ne peut pas ˆtre   e
               e    `                   e
directement d´fini a partir de cette s´mantique.
                                     Chapitre 4

               e           e
              S´mantique op´rationnelle

         e                                            e                                 e
     La s´mantique comportementale que nous avons d´finie dans le chapitre 3 n’est pas op´ration-
               e                 e             e
nelle : elle pr´sente ce qu’une r´action doit v´rifier mais pas comment la calculer. En particu-
                                        e          e           e               e
lier, l’environnement de signaux doit ˆtre devin´ avant la r´action. Nous pr´sentons ici une
 e            `              u     e
s´mantique a petits pas o` la r´action construit l’environnement de signaux. Ce travail est
      e
publi´ dans [69].


4.1      e         a
        S´mantique ` petits pas
       e             e                e
   La s´mantique op´rationnelle est d´compos´e en deux ´tapes. La premi`re d´crit la r´action
                                               e           e             e    e       e
                                                    e                 e           e e
pendant l’instant comme une succession de micro-r´actions. La seconde ´tape, appel´e r´action
                   e        e
de fin d’instant pr´pare la r´action pour l’instant suivant.

4.1.1    e         a e
        S´mantique ` r´duction
              e e                e                                   e            ` e
   La premi`re ´tape de la s´mantique est une extension de la s´mantique a r´duction de
                     e                             e   e                           e
ML [88, 107]. La r´action d’un instant est repr´sent´e par une succession de r´actions de la
forme e/S → e /S o` S est un environnement de signaux d´fini comme dans le chapitre 3.3.1.
                       u                                     e
     e           e             e
Ces r´ductions d´finissent la r´action du programme tout en construisant l’ensemble des valeurs
e
´mises.
   Pour d´finir la r´action →, on commence par se donner des axiomes pour la relation de
           e           e
 e             e                                         e
r´duction en tˆte de terme (→ε ). Ces axiomes sont donn´s dans la figure 4.1.
                                                         e
   – Les axiomes pour l’application et le rec sont les mˆmes que pour ML.
          e               e                                                        e
   – La r`gle pour la s´quence indique qu’une fois que la branche gauche est r´duite en une
                                      e         e
      valeur, alors cette valeur peut ˆtre oubli´e.
                                  e                                        e              e
   – Le let/and/in peut se r´duire lorsque les deux expressions calcul´es en parall`le sont
       e
      r´duites en des valeurs.
                          `        e                                 e
   – Le run s’applique a une d´finition de processus. Il permet son ´valuation.
                     e                                                     e
   – emit n v se r´duit en () et ajoute v au multi-ensemble des valeurs ´mises sur n.
                                       e    e                                 e
   – La construction present peut ˆtre r´duite seulement si le signal est pr´sent dans l’envi-
      ronnement.
          e                 e                                                               u
   – La r´duction de la d´claration d’un signal x dans une expression e renomme x en n o` n est
      un nom frais appartenant a N . n est ajout´ a l’environnement de signaux avec v 1 comme
                                   `              e`
                   e
      valeur par d´faut, v2 comme fonction de combinaison et (false, v1 ) pour l’initialisation du

                                               65
66                                    e           e
                                  4. S´mantique op´rationnelle




        λx.e v/S →ε e[x ← v]/S       rec x = e/S →ε e[x ← rec x = e]/S      v;e/S →ε e/S

     run (process e)/S →ε e/S       let x1 = v1 and x2 = v2 in e/S →ε e[x1 ← v1 , x2 ← v2 ]/S

        emit n v/S →ε ()/S + [v/n]        present n then e1 else e2 /S →ε e1 /S si n ∈ S

 signal x default v1 gather v2 in e/S →ε e[x ← n]/S[(v1 , v2 , (false, v1 ), ∅)/n] si n ∈ Dom(S)

           do v until n(x) -> e done/S →ε v/S         do v when n/S →ε v/S si n ∈ S

            pre n/S →ε b/S si S p (n) = (b, v)     pre ?n/S →ε v/S si S p (n) = (b, v)



                                             e            e
                                 Fig. 4.1 – R´duction en tˆte

                                                e`
      pre. Initialement le multi-ensemble associ´ a n est vide car les signaux sont absents par
       e
      d´faut.
                                                                                        e
   – Lorsque le corps d’une construction do/until est une valeur, cela signifie que la r´action
                 e
      est termin´e. Donc le do/until retourne la valeur de son corps.
   – Et le do/when peut rendre une valeur quand son corps est une valeur et le signal est
        e
      pr´sent.
   – Les pre vont chercher dans l’environnement leur valeur.
                     e          e             e           e                         e
   Nous venons de d´finir les r´ductions en tˆte. Nous d´finissons maintenant la r´duction en
profondeur (→) :

                 e/S →ε e /S                       n∈S     e/S → e /S
              Γ(e)/S → Γ(e )/S          Γ(do e when n)/S → Γ(do e when n)/S

 u                     e                          e   e                       e         e
o` Γ est un contexte d’´valuation. Dans la premi`re r`gle, l’expression e se r´duit en tˆte, donc
              e                                                   e    e
elle peut se r´duire dans n’importe quel contexte. La seconde r`gle d´finit la suspension. Elle
                                           e    e     e                       e
montre que le corps d’un do/when ne peut ˆtre ´valu´ que si le signal est pr´sent.
                    e                e              c
    Les contextes d’´valuation sont d´finis de la fa¸on suivante :

      Γ ::=      [ ] | Γ e | e Γ | (Γ, e) | (e, Γ) | Γ;e | run Γ
               | let x = Γ and x = e in e | let x = e and x = Γ in e
               | emit Γ e | emit e Γ
               | present Γ then e else e
               | signal x default Γ gather e in e | signal x default e gather Γ in e
               | do e until Γ(x) -> e done | do Γ until n(x) -> e done
               | do e when Γ
               | pre Γ | pre ?Γ

                  e                                 e
Si on reprend la d´finition de la composition parall`le, les deux contextes possibles sont Γ||e
                                              e                      e e
et e||Γ. Ces contextes montrent que l’ordre d’´valuation n’est pas sp´cifi´. Dans l’implantation
                                                       e                   e
de ReactiveML, le choix de l’ordonnancement est fix´ de sorte que l’ex´cution soit toujours
                                         e         `
                                   4.1. S´mantique a petits pas                                67



                                                                      O    e1 →eoi e1
                 O    v →eoi v      O       pause →eoi ()
                                                                  O   e1 ;e2 →eoi e1 ;e2

                                                  n∈O
                               O   present n then e1 else e2 →eoi e2

                                   O    e1 →eoi e1    O       e2 →eoi e2
             O       let x1 = e1 and x2 = e2 in e →eoi let x1 = e1 and x2 = e2 in e

                                             O(n) = (true, v)
                          O    do e1 until n(x) -> e2 done →eoi e2 [x ← v]

                                        n∈O       O   e1 →eoi e1
             O       do e1 until n(x) -> e2 done →eoi do e1 until n(x) -> e2 done

                 n∈O       O     e →eoi e                                  n∈O
         O    do e when n →eoi do e when n                O     do e when n →eoi do e when n


                                             e
                                 Fig. 4.2 – R´action de fin d’instant

                       e         `
reproductible d’une ex´cution a l’autre. Nous reviendrons plus tard (chapitre 10) sur l’ordre
    e                e
d’ex´cution du parall`le et les choix faits dans les autres langages.
            e                                                                          e
    On note ´galement que do Γ when n n’est pas un contexte car on ne veut pas pouvoir ´valuer
dans un do/when lorsque le signal n est absent.


4.1.2    e
        R´action de fin d’instant
            e e              e                     e                e `
   Le mod`le r´actif est bas´ sur l’absence de r´action instantan´e a l’absence d’un signal. Il
                                                                           e
faut donc attendre la fin d’instant pour traiter l’absence des signaux et pr´parer le programme
pour l’instant suivant.
                                                                                     `
   La r´action de l’instant s’arrˆte lorsqu’il n’y a plus de r´ductions → possibles. A partir de
        e                        e                            e
                                                 e                                    e
ce moment, l’environnement des signaux est fig´, il ne peut plus y avoir de nouvelles ´missions.
                          eee                    e
Les signaux qui n’ont pas ´t´ ´mis sont suppos´s absents. On peut alors calculer la sortie O du
                                    e
programme avec la fonction next d´finie dans le chapitre 3.3.2 (page 51).
   Les r`gles pour le traitement de fin d’instant ont la forme suivante : O e →eoi e . Leur
         e
 e                  e                                                 e
d´finition est donn´e figure 4.2. Nous pouvons remarquer que les r`gles ne sont donn´es quee
                                                              e
pour un sous-ensemble d’expressions car elles seront appliqu´es seulement quand l’expression e
ne peut plus ˆtre r´duite par →. Nous verrons chapitre 5 que les expressions biens typ´es se
              e     e                                                                      e
 e
r´duisent toujours dans une expression de cette forme.
                      e
   Commentons les r`gles de la figure 4.2 :
                                  e           e
   – Les valeurs restent inchang´es par la r´duction.
68                                      e           e
                                    4. S´mantique op´rationnelle

                                       e                   `
     – L’instruction pause peut se r´duire uniquement a la fin de l’instant.
                                                   e            `                           e
     – Le traitement de fin d’instant est appliqu´ seulement a la blanche gauche de la s´quence
                                             e
       car la branche droite n’est pas activ´e pendant l’instant.
             e         e
     – De mˆme, la r´duction de fin d’instant ne s’applique qu’aux deux expressions de la partie
       gauche du let/and/in.
                                           `
     – S’il y a une instruction present a la fin d’instant, c’est que le signal est absent. Donc
       a l’instant suivant il faudra ex´cuter la branche else. La notation n ∈ O indique que le
       `                                 e
                     e`
       statut associ´ a n dans O est false.
                               e                                                    o
     – Le traitement de la pr´emption a lieu en fin d’instant. Si le signal qui contrˆle le do/until
              e                         e      e     e
       est pr´sent, l’expression doit ˆtre pr´empt´e. Dans ce cas, le code de traitement de la
         e                    e       e e`
       pr´emption (e2 ) doit ˆtre ex´cut´ a l’instant suivant avec x qui prend la valeur du signal.
                                               e
     – Et pour le do/when, si le signal est pr´sent, il faut propager le traitement de fin d’instant.
       Si le signal est absent, le corps du do/when est suspendu.

4.1.3       e
          Ex´cution d’un programme
         e                         e
     L’ex´cution d’un instant est d´finie par la relation :

                                           ei /Si ⇒ ei /Si

                              e                         e
Si on note Ii et Oi les entr´es et les sorties de la r´action de l’instant, l’environnement des
                               ee                                           e
signaux doit avoir les propri´t´s suivantes. Tous les signaux sont par d´faut absents sauf les
signaux donn´s en entr´e (Ii = Si
               e         e          v ). Les sorties sont calcul´es a partir de l’environnement a
                                                                e `                              `
la fin de la r´action (Oi = next(Si )). Les valeurs par d´faut, les fonctions de combinaison des
              e                                             e
                                                                       g
signaux sont conserv´es d’un instant a l’autre (Sid = Si+1 et Sig = Si+1 ). Les sorties d´finissent
                      e                 `                 d                              e
                                    p
le pre de l’instant suivant (Oi = Si+1 ).
        e                         e                   e          e                    a
    L’ex´cution d’un instant se d´compose en deux ´tapes : la r´duction de e i jusqu’` l’obtention
                              e           `
d’un point fixe ei , puis la pr´paration a l’instant suivant.

                         ei /Si → ei /Si   Oi = next(Si )    Oi   ei →eoi ei
                                           ei /Si ⇒ ei /Si

o` e/S → e /S si e/S →∗ e /S et e /S →. La relation →∗ est la fermeture r´flexive et
 u                                                                       e
transitive de →.


4.2      ´                    e
         Equivalence avec la s´mantique comportementale
                           e              e               e          `     e
   Nous montrons que la s´mantique op´rationnelle est ´quivalente a la s´mantique comporte-
                                   ee                                              e
mentale (chapitre 3). Cette propri´t´ permet de choisir le formalisme le plus adapt´ en fonction
          ee `
des propri´t´s a montrer.
                  c                                           e
   Nous commen¸ons par prouver que si une expression e r´agit en une expression e avec la
 e          `                             e              e
s´mantique a petits pas, alors elle peut r´agir dans le mˆme environnement de signaux avec la
 e
s´mantique grands pas.

   e e
Th´or`me 1
Pour tout environnement Sinit et expression e tels que e/Sinit ⇒ e /S, alors il existe N , E et b
                 E, b
tels que N                            v
               e − → e avec E = S v \Sinit .
                  −
                  S
                              ´                    e
                         4.2. Equivalence avec la s´mantique comportementale                          69


          e/S        G                     G en−2 /Sn−2    G en−1 /Sn−1       G en /S            Ge
                                                                                                eoi
                                                                                          .-,
                                                                                        (/)*+
                                                                                          A
                                                                                      ∅,b
          e/S        G                     G en−2 /Sn−2    G en−1 /Sn−1       G en /S • • •G e
                                                                                       S
                                                                              7654
                                                                              0123
                                                                               B
          e/S        G                     G en−2 /Sn−2                      E
                                                           G en−1 /Sn−1 • • • 1 ,b• • • • •G e
                                                                               •
                                                                              S




                                              E,b
          e/S • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •G e
                                              S


                                                                   e e
                            Fig. 4.3 – Structure de la preuve du th´or`me 1.


 e
D´monstration :
   La preuve se fait par induction sur le nombre de r´ductions → dans e/Sinit ⇒ e /S.
                                                     e
   – S’il n’y a pas de r´ductions → possibles, il faut montrer que la r´duction →eoi est
                         e                                                e
     e           `     e
     ´quivalente a la s´mantique grands pas (lemme 2).
   – S’il y a au moins une r´duction →, on doit montrer qu’une r´duction → suivie d’une
                             e                                     e
      e                      e            `     e
     r´action grands pas est ´quivalente a une r´action grands pas (lemme 3).
                                     e                                     e
   Le diagramme de la figure 4.3 repr´sente la structure de la preuve. Les fl`ches pleines sont
           e                                e          e
   quantifi´es universellement (∀) et les fl`ches hachur´es le sont existentiellement (∃). Les
   diagrammes A et B correspondent respectivement aux lemmes 2 et 3.
                                e                ee
   La preuve de ce lemme est bas´e sur les propri´t´s suivantes :

Lemme 2
                                                                    ∅, b
Si e/S → et S       e →eoi e , alors il existe N et b tel que N     −
                                                                  e −→ e .
                                                                     S

 e
D´monstration :
   La preuve se fait par induction sur la structure de e.

Lemme 3
                                 E ,b
Si e/S0 → e1 /S1 et N            −→
                              e1 − − e avec S1       S
                                  S
             E, b                         v   v
alors N      −
          e − → e avec E = E            (S1 \S0 ).
                S

 e
D´monstration :
                             e                              e          ee         e
   La preuve se fait en deux ´tapes. On montre d’abord la mˆme propri´t´ pour la r´duction
   →ε . Puis on montre que cette propri´t´ est vraie dans tout contexte Γ.
                                        ee
                                                        e               e
    On montre maintenant que si un programme peut r´agir dans le mˆme environnement avec
          e                                          `            e                  e
les deux s´mantiques, alors les expressions obtenues a la fin des r´actions sont les mˆmes. On a
       e                           e
donc l’´quivalence entre les deux s´mantiques.
70                                       e           e
                                     4. S´mantique op´rationnelle

   e e
Th´or`me 2
Pour chaque Sinit et e tels que :
              E1 , b 1
     – N       −→
            e − − e1 o` S1 est le plus petit environnement tel que Sinit
                      u                                                       S1
                S1
    – e/Sinit ⇒ e2 /S2
                         g
    – ∀n ∈ Dom(S2 ) : S2 (n) = f et f (x, f (y, z)) = f (y, f (x, z)),
alors e1 = e2 et S1 = S2
 e
D´monstration :
                                                                 E2 , b 2
   Avec le th´or`me 1, il existe E2 et b2 tels que N
             e e                                                 −→
                                                              e − − e2 et on peut remarquer, par
                                                                   S2
      construction, que S2 est le plus petit environnement tel que Sinit S2 .
                     ee           e        ee
      Avec la propri´t´ d’unicit´ (propri´t´ 2), nous savons qu’il existe un unique plus pe-
                                                                       e           e
      tit environnement de signaux dans lequel une expression peut r´agir avec la s´mantique
                                                            e                 e
      comportementale donc S1 = S2 . Maintenant, avec le d´terminisme de la s´mantique (pro-
         ee
      pri´t´ 1) on a E1 = E2 , b1 = b2 et e1 = e2 .



4.3                                     e
           Ajout des constructions non d´terministes
                        e                 e                                       `    e
    Afin de donner la s´mantique compl`te du langage, nous ajoutons maintenant a la s´mantique
     ee                        e     e   e             e                     e
les r´f´rences et la possibilit´ de r´cup´rer instantan´ment une des valeurs ´mises sur un signal.
                                                 e                e
    Ces deux constructions font perdre le d´terminisme des r´actions. Par exemple, le pro-
gramme :
let x = ref 0 in
(x := 1 || x := 2);
print_int !x
                          e                                  e                       e
peut afficher 1 ou 2. L’ind´terminisme vient de l’absence de sp´cification de l’ordre d’´valuation
                   e         e
des branches parall`les. De mˆme, dans le programme suivant :
signal s in
emit s 1; emit s 2;
await one s(x) in print_int x
                                                    e
comme l’environnement des signaux n’est pas ordonn´, await/one ne peut donner aucune ga-
rantie sur la valeur que va prendre x. Le programme peut donc afficher lui aussi 1 ou 2.
                         e          e         e                         e
   On veut pouvoir refl´ter ces diff´rentes ex´cutions possibles dans la s´mantique.
Remarque :
              e        e
   Il y a le mˆme probl`me en Ocaml avec les paires par exemple :
      let x = ref 0 in (x := 1, x := 2)
                 e                     e e             e            e                    e
      L’ordre d’´valuation n’est pas sp´cifi´, mais l’ex´cution est d´terministe. Si on ex´cute
                    e                             e     e
      deux fois le mˆme programme, il donne le mˆme r´sultat.

4.3.1      Await/one
   Nous avons vu chapitre au 2 qu’il existe deux formes de await/one. Une seule des deux est
primitive. On a
                                        def
               await one s(x) in e      =     await immediate one s(x) in pause;e
                                                          e
                        4.3. Ajout des constructions non d´terministes                                      71

On ajoute donc la construction await immediate one e(x) in e aux expressions du noyau.
                              e ::=         ...
                                          | await immediate one e(x) in e
          e                                                               e        e
Afin de d´crire le comportement de cette construction, il faut ajouter la r`gle de r´duction en
 e
tˆte de terme suivante :
           await immediate one n(x) in e/S →ε e[x ← one(S v (n))]/S                              si   n∈S
  u                                                                           u
 o` one est une fonction qui retourne une valeur d’un multi-ensemble. On est sˆr que le multi-
ensemble n’est pas vide car on a la condition n ∈ S.
            e         e
    Il faut ´galement ´tendre les contextes :
                           Γ ::=            ...
                                          | await immediate one Γ(x) in e
               e                         e            e `
    Enfin, la r`gle de fin d’instant peut ˆtre appliqu´e a await/one si le signal est absent. Dans
                          `                             e
ce cas, il faut continuer a attendre que le signal soit ´mis.
                                                      n∈O
           O    await immediate one n(x) in e →eoi await immediate one n(x) in e
                              e            e
   On peut aussi facilement ´tendre la s´mantique comportementale du chapitre 3 avec cette
                                     e                      e
construction. Il suffit d’ajouter les r`gles suivantes au syst`me de transition :
                                             E, true
                                      N      −−
                                           e −−→ n                        n∈S
                                                  S
                                                          E, false
       N                                       −−
               await immediate one e(x) in e1 − − → await immediate one n(x) in e1
                                                               S

                        E, true                                                            E1 , b
                  N     −−
                      e −−→ n             n∈S             N1       e1 [x ← one(S v (n))] − − e1
                                                                                         −→
                          S                                                                  S
                                                                                E E1 , b
                      N · N1                                     − −→
                                  await immediate one e(x) in e1 − − − e1
                                                                                   S

                                 e             e                     e             e
   On peut remarquer que la s´mantique op´rationnelle est plus pr´cise que la s´mantique
                                                     e           e
comportementale. Dans l’exemple suivant, avec la s´mantique op´rationnelle la seule valeur
                                        e                                      e    e    `
possible pour x est 1 alors qu’avec la s´mantique comportementale x peut aussi ˆtre ´gal a 2 :
signal s in
emit s 1;
await immediate one s(x) in
emit s 2;
print_int x
              e                             e
   Enfin, les r`gles de bonne formation sont ´tendues par :
                                              0       e        1     e1
                                  1   await immediate one e(x) in e1
    e                                                                        e           e
La r`gle de bonne formation indique que la construction await/one ne peut ˆtre utilis´e que
                                        e
dans un contexte de processus car son ex´cution peut prendre plusieurs instants si le signal est
absent.
72                                         e           e
                                       4. S´mantique op´rationnelle

4.3.2          ee
          Les r´f´rences
                                                    ee
   L’extension du noyau de ReactiveML avec les r´f´rences se fait comme pour l’extension
                                         e               e     e               e     e
de ML. On introduit la notion d’adresse m´moire (l) et d’´tat m´moire (M ). Un ´tat m´moire
                                 e
M est une fonction des adresses m´moires dans les valeurs.

                                         M ::= [v1 /l1 , ..., vn /ln ]

                           e           ee                                            eee
   On ajoute au noyau la d´finition de r´f´rences (ref e), l’affectation (e := e), le d´r´f´rencement
                      e
(!e) et les adresses m´moires (l) :

                                  e ::=       . . . | ref e | e := e | !e | l

               e            e              e `
Les adresses m´moires sont ´galement ajout´es a l’ensemble des valeurs.
       e             e                                              e     e           e
   La s´mantique op´rationnelle doit maintenant prendre en compte l’´tat m´moire. La r´action
d’un instant devient donc :
                    ei /Si , Mi → ei /Si , Mi       Oi = next(Si )        Oi    ei →eoi ei
                                          ei /Si , Mi ⇒ ei /Si , Mi
avec les relations → et →ε ´tendues avec les ´tats m´moires.
                           e                 e       e
         e         e
   Les r`gles de r´duction des nouvelles expressions sont :
     ref v/S, M →ε l/S, M [v/l] si l ∈ Dom(M )               !l/S, M →ε M (l)/S, M si l ∈ Dom(M )

                         l := v/S, M →ε ()/S, M [v/l] si l ∈ Dom(M )
            e                           e             e                       e          e
Toutes les r`gles du noyau laissent la m´moire inchang´e, seul les nouvelles r`gles y acc`dent.
                   e        e
   Pour finir de d´crire la s´mantique, on augmente les contextes :

                             Γ ::=         . . . | ref Γ | Γ := e | e := Γ | !Γ

 e
S´mantique comportementale
                                        e
    Nous ne pouvons pas donner la s´mantique comportementale du langage avec r´f´rencesee
                                         e              e     e              e
car l’entrelacement des branches parall`les ne peut pas ˆtre d´crit. Le probl`me s’illustre si on
                     e             e
essaye de donner la r`gle du parall`le.
                           E1 , b 1                            E2 , b 2
               N1          −→
                    e1 /M − − e1 /M2          N2             −→
                                                      e2 /M − − e2 /M2           b1 ∧ b2 = false
                              S                                    S
                                                   E1 E2 , false
                       N1 · N2                    −−−→
                                      e1 ||e2 /M − − − − e1 ||e2 /(M1             M2 )
                                                        S

                  e                   e                    e                      e
On voit que la r´action de e1 ne d´pend pas de M2 et r´ciproquement, e2 ne d´pend pas de M1 .
                       e                                  e    ee
De plus, comment d´finir si e1 et e2 modifient la mˆme r´f´rence ?
                          e                                e
     Une solution peut ˆtre d’interdire les lectures et ´critures sur une partie commune de la
   e                                       e             e
m´moire par les deux branches parall`les. Le probl`me de cette approche est qu’elle r´duit   e
              e
l’expressivit´ du langage. De plus, il est difficile de faire une analyse statique qui garantit
              ee               `
cette propri´t´ et qui soit a la fois modulaire et suffisamment fine pour le pas rejeter trop de
programmes.
                                    e          `
     On voit ici les limites de la s´mantique a grands pas. Comme elle abstrait l’ordonnancement
`      e                                                                   e       e           e
a l’int´rieur de l’instant, elle ne peut pas exprimer un dialogue instantan´ par m´moire partag´e.
                                       4.4. Conclusion                                        73

4.4    Conclusion
                              e             e                                       e
    Ce chapitre introduit la s´mantique op´rationnelle de ReactiveML. C’est une s´mantique
`             e            e                                                   e          e
a petits pas d´crivant la r´action d’un instant comme une succession de micro-r´actions. Mˆme
          e              `                        e
si cette s´mantique est a grains fins, elle ne sp´cifie pas l’ordonnancement des calculs. Ainsi
        e                                           e
cette s´mantique offre un bon formalisme pour v´rifier la correction des implantations. En
                            e            e e                                              e
effet, l’ordonnancement n’´tant pas sp´cifi´, tous les ordonnancements possibles peuvent ˆtre
        e
exprim´s.
                  e                    e            e                 e
    La preuve d’´quivalence entre la s´mantique op´rationnelle et la s´mantique comportemen-
       ee e e                                         e
tale a ´t´ r´alis´e. Nous disposons ainsi d’un cadre s´mantique large avec deux formalisations
                                   e
du langage qui sont de nature diff´rente.


 e   e
R´sum´
                                                 e           `
    Nous avons introduit dans ce chapitre une s´mantique a petits pas du langage qui permet de
  e                                                                     e               e
d´finir la construction de l’environnement des signaux au cours de la r´action. Cette s´mantique
      e            e                 e                   e         ` e                         e
est d´finie en deux ´tapes. La premi`re s’inspire de la s´mantique a r´duction de ML. Elle d´crit
    e                                                            e               a
la r´action pendant l’instant comme une succession de micro-r´actions jusqu’` l’obtention d’un
                                                                      e
point fixe. Une fois le point fixe obtenu, le programme ne peut plus ´mettre de signaux pendant
                       e                    e                                   e          e
l’instant. La seconde ´tape peut alors g´rer l’absence des signaux pour pr´parer la r´action
                                          e            e             e             `    e
de l’instant suivant. Nous avons montr´ que cette s´mantique est ´quivalente a la s´mantique
                                  e e
comportementale du chapitre pr´c´dent.
                       e                                                             ee
    Enfin, nous avons ´tendu le langage avec la construction await/one et les r´f´rences. Ces
                               e                   e                                         e
constructions font perdre le d´terminisme de la s´mantique. En voulant conserver le parall`le as-
                                                                         e
sociatif et commutatif, il ne peut pas y avoir de solution unique pour l’´valuation du programme
suivant :
let x = ref 0 in (x := 1 || x := 2)
                                     Chapitre 5

                                        Typage

                                      e                                  e
   Nous terminons la partie sur la s´mantique de ReactiveML en pr´sentant le syst`me de  e
                                        u e           e
type du langage ainsi que sa preuve de sˆret´. Ce syst`me de type est une extension conservative
       e                                                                          e
du syst`me de type de ML, garantissant que tous les programmes ML bien typ´s restent bien
   e                   e                                   e
typ´s et gardent le mˆme type. Ce point est important d`s lors que l’on souhaite plonger le
     e
mod`le dans un langage existant.


5.1     Extension du typage de ML
            e                                                          e
    Le syst`me de type de ReactiveML est une extension du syst`me de type de ML de Mil-
                                                                                    e
ner [73]. Nous devons traiter les signaux et en particulier les valeurs qui peuvent ˆtre transmises
sur les signaux. Le langage de type est :
                    σ   ::= ∀α1 , . . . , αn .τ
                    τ   ::= T | α | τ → τ | τ × τ | τ process | (τ, τ ) event
                    T   ::= int | bool | . . .
                   e
Un type (τ ) peut ˆtre un type de base (T ), une variable de type (α), le type d’une fonction
(τ1 → τ2 ), un type produit (τ1 × τ2 ), le type d’un processus param´tr´ par sa valeur de retour
                                                                     e e
(τ process) ou le type d’un signal ((τ1 , τ2 ) event). Dans le type (τ1 , τ2 ) event, τ1 est le type
            e                                    e                                  e
des valeurs ´mises sur le signal alors que τ2 d´signe le type de la valeur associ´e au signal en
                    e                                       e
lecture (obtenu apr`s la combinaison de toutes les valeurs ´mises pendant un instant). σ est un
    e
sch´ma de type.
                                  ee                          e e
    Comme pour le typage des r´f´rences, il ne faut pas g´n´raliser le type des expressions
      e                                                 e e
qui cr´ent des signaux. Par exemple, il ne faut pas g´n´raliser le type de x dans l’expression
suivante :
  let x = signal s in s in
  emit x 1; emit x true
Si on donnait le type ∀α.(α, α multiset) event a x, on accepterait le programme qui pour-
                                                    `
tant est incorrect. Ainsi, les expressions expansives et les expressions non-expansives sont dis-
     e                       e                              e
tingu´es [103, 106]. Cette s´paration est faite sur des crit`res syntaxiques. Les expressions non-
                        e
expansives (ene ) sont d´finies par :
         ene ::=       x | c | (ene , ene ) | λx.e | process e
                     | let x = ene and x = ene in ene | present ene then ene else ene
                     | emit ene ene | pause | pre ene | pre ?ene
                     | do ene until ene (x) -> ene done | do ene when ene

                                                75
76                                                 5. Typage

                            e
Nous remarquons que les d´clarations de signaux et les applications ne font pas partie des
expressions non-expansives.
                                               e
   Un environnement de typage H associe un sch´ma de type aux variables et des types aux
noms de signaux :

                          H ::= [x1 : σ1 ; . . . ; xk : σk ; n1 : τ1 ; . . . ; nk : τk ]

                       e e                 e
L’instanciation et la g´n´ralisation sont d´finies comme suit :

      τ [τ1 /α1 , . . . , τn /αn ] ≤ ∀α1 , . . . , αk .τ
                               ∀α1 , ..., αn .τ o` {α1 , ..., αk } = f v(τ ) − f v(H) si e non-expansive
                                                   u
      Gen(H, e, τ ) =
                               τ sinon

                             e
     Les expressions sont typ´es dans un environnement de typage initial T C tel que :

                           T C = [true : bool; fst : ∀α, β. α × β → α; ...]

                            e               e
Les expressions sont typ´es par un pr´dicat de la forme H e : τ qui se lit “e a le type τ dans
                                            e           e
l’environnement de typage H”. Ce pr´dicat est d´fini figure 5.1.
             e
    – Les r`gles de typage des expressions ML ne sont pas modifi´es.      e
                                                                                         e e
    – Pour le typage de let/and/in, le type des variables qui sont introduites est g´n´ralis´   e
       uniquement si les expressions e1 et e2 sont non-expansives.
                                                      e                                   e
    – Dans le typage de signal, la valeur par d´faut (e1 ) a le type de la valeur combin´e et la
                                                                             e           e
       fonction de combinaison (e2 ) est une fonction qui prend en param`tre une valeur ´mise et
                                         eae
       la combinaison des valeurs d´j` ´mises et retourne la nouvelle combinaison.
            e                 e
    – La r`gle pour emit v´rifie que le premier argument est de type (τ1 , τ2 ) event (le type des
                                                 e
       signaux) et que le type de la valeur ´mise est τ1 .
                                          e    e                  e `                  e
    – do e1 until e(x) -> e2 done r´cup`re la valeur associ´e a un signal en cas de pr´emption.
       Ainsi, si e a le type (τ1 , τ2 ) event, x doit avoir le type τ2 .
                                              e `
    – L’instanciation run e est appliqu´e a un processus.
                                                                e          e `
    – Les constructions present, until et when peuvent ˆtre appliqu´es a n’importe quel signal.
             e                                                                   e
    Nous d´finissons maintenant la notion d’environnement de signaux bien typ´. Elle est not´e  e
                                                 e
H S. Un environnement S est bien typ´ dans un environnement H si les environnements S
                          e
et H contiennent les mˆmes signaux :

                                      n ∈ Dom(S) ⇔ n ∈ Dom(H)

et que pour tout signal n ∈ Dom(S), il existe un type (τ1 , τ2 ) event tel que :

                                       H(n) = (τ1 , τ2 ) event
                                       H S d (n) : τ2
                                       H S g (n) : τ1 → τ2 → τ2
                                       H S p (n) : bool × τ2
                                       H S m (n) : τ1 multiset

         e                                              e
   De mˆme, pour l’environnement de fin d’instant, nous d´finissons le jugement H                       O. Donc
              e
O est bien typ´ dans H si pour tout signal n :

                                      n ∈ Dom(O) ⇔ n ∈ Dom(H)
                                      H(n) = (τ1 , τ2 ) event
                                      H O(n) : bool × τ2
                                    5.1. Extension du typage de ML                                                          77




τ ≤ H(x)               τ ≤ T C(c)                H      e 1 : τ1       H      e 2 : τ2                H[x : τ1 ]   e : τ2
H   x:τ                 H       c:τ               H         (e1 , e2 ) : τ1 × τ2                   H      λx.e : τ1 → τ2

                    H         e 1 : τ1 → τ 2      H         e 2 : τ1            H[x : τ ]        e:τ
                                    H     e 1 e2 : τ2                           H       rec x = e : τ

H   e 1 : τ1   H         e 2 : τ2       H[x1 : Gen(H, (e1 , e2 ), τ1 ); x2 : Gen(H, (e1 , e2 ), τ2 )]                 e:τ
                                 H        let x1 = e1 and x2 = e2 in e : τ

                                H       e:τ                            H      e 1 : τ1      H      e 2 : τ2
               H         process e : τ process                                  H       e1 ;e2 : τ2

               H       e : τ process                  H       e1 : (τ1 , τ2 ) event          H        e 2 : τ1
                   H      run e : τ                              H       emit e1 e2 : unit

                            H       e : (τ, τ ) event          H       e1 : τ       H     e2 : τ
                                    H      present e then e1 else e2 : τ

          H        e 1 : τ2     H        e 2 : τ1 → τ 2 → τ 2            H[s : (τ1 , τ2 ) event]            e:τ
                            H       signal s default e1 gather e2 in e : τ

                     H        e : (τ1 , τ2 ) event        H        e1 : τ     H[x : τ2 ]        e2 : τ
                                  H       do e1 until e(x) -> e2 done : τ

               H         e1 : (τ1 , τ2 ) event          H      e:τ
                            H       do e when e1 : τ                            H        pause : unit

                        H       e : (τ1 , τ2 ) event                 H       e : (τ1 , τ2 ) event
                            H       pre e : bool                         H      pre ?e : τ2



                                                         e
                                          Fig. 5.1 – Syst`me de type
78                                              5. Typage

                         ee
    Nous avons les propri´t´s suivantes sur les environnements de signaux. Si pour tout H, S et
n tels que O = next(S) alors

        H    S implique H   O    et    n ∈ S implique n ∈ O     et   n ∈ S implique n ∈ O


5.2      Preuve de sˆ ret´ du typage pour la r´duction →
                    u e                       e
                                              u e                              e
   Les techniques classiques de preuve de sˆret´ du typage [87] sont utilis´es. La principale
   e                    e                                                  a        e
diff´rence vient de la d´finition des expressions en forme normale vis-`-vis de la r´duction
→. Ces expressions ne sont pas des valeurs mais des expressions sur lesquelles nous pouvons
appliquer la r´duction →eoi . Elles sont appel´es expressions de fin d’instant.
              e                               e
         e                e
   La pr´sentation suit fid`lement les preuves de [62].

   e e           u e
Th´or`me 3 (Sˆ ret´ du typage)
Si T C e : τ et k e et e/S →∗ e /S et e /S est en forme normale vis-`-vis de →, alors e est
                                                                    a
une expression de fin d’instant.
 e
D´monstration :
        e                                      ee
   La d´monstration repose sur les deux propri´t´s suivantes :
   – la pr´servation du typage par la r´duction →
           e                           e
                                 e
   – les formes normales bien typ´es sont des expressions de fin d’instant.


5.2.1         e
            Pr´servation du typage
          e              ee       e                                c         e
    Pour d´finir la propri´t´ de pr´servation du typage, nous commen¸ons par d´finir la relation
e
ˆtre moins typable.

 e             e
D´finition 5 (ˆtre moins typable)
Nous disons que e1 /S1 est moins typable que e2 /S2 (e1 /S1 e2 /S2 ) si pour tout environnement
H et pour tout type τ :
   – Si e1 est non-expansive alors e2 est non-expansive et de plus :

                        H    e1 : τ et H   S1     implique H   e2 : τ et H   S2

                                              e
     – Si e1 est expansive, alors il existe H ´tendant H tel que :

                        H    e1 : τ et H   S1    implique H    e2 : τ et H   S2

        L’environnement H ´tend H si pour tout x ∈ Dom(H) et pour tout n ∈ Dom(H),
                             e
        H(x) = H (x) et H(n) = H (n) et il peut exister des noms de signaux n ∈ Dom(H ) qui
        ne sont pas d´finis dans H (n ∈ Dom(H)).
                     e
    La pr´servation du typage par la r´duction → montre que si une expression e est bien typ´e
          e                             e                                                   e
            e                                               e           e
et elle se r´duit en une expression e , alors e est bien typ´e et a le mˆme type.

               e
Lemme 4 (Pr´servation du typage)
Si e/S → e /S , alors e/S e /S
         e
     La d´monstration utilise le lemme de substitution.
                     5.2. Preuve de sˆret´ du typage pour la r´duction →
                                     u e                      e                                               79

Lemme 5 (Lemme de substitution)
Supposons
                  H e : τ et H[x : ∀α1 , . . . , αn .τ ]                     e:τ
                                                                  e
avec α1 , . . . , αn non libres dans H, et aucune des variables li´es dans e n’est libre dans e . Alors,

                                           H       e[x ← e ] : τ

 e
D´monstration :
        e                                                                e
   La d´monstration de ce lemme est comme pour ML. Elle se fait par r´currence sur la struc-
   ture des expressions. Pour les expressions qui n’introduisent pas d’identificateur, la preuve
                                     e        e
   se fait directement avec l’hypoth`se de r´currence. Pour les constructions signal/in et
                               e                             e
   do/until, elle utilise le mˆme principe que pour la d´finition de fonctions. Et le cas
   let/and/in se prouve comme un let/in.
                                   e
   Maintenant, pour prouver la pr´servation du typage, nous traitons les cas de base en
 e              e                              e             e
d´montrant la pr´servation du typage pour les r´ductions en tˆte de terme.

              e                      e            e
Lemme 6 (Pr´servation du typage par r´duction de tˆte)
Si e/S →ε e /S , alors e/S e /S
 e
D´monstration :
             ee
   La propri´t´ e non-expansive implique e non-expansive se montre directement par examen
        e         e                         e                    e                         e
   des r`gles de r´duction. Le reste de la d´monstration se fait ´galement par cas sur la r`gle
       e              e
   de r´duction utilis´e.
      Cas run (process e)/S →ε e/S : Par hypoth`se, H run (process e) : τ et H
                                                    e                                                     S. La
       e
      d´rivation de typage de l’expression run (process e) est de la forme :

                                                     H    e:τ
                                       H       (process e) : τ process
                                           H       run (process e) : τ

      Nous avons donc H                        e
                               e : τ . Par cons´quent, run (process e)/S             e/S.
      Cas emit n v/S →ε ()/S + [v/n] : Puisque emit n v est bien typ´e dans H, nous avons
                                                                    e
          e
      la d´rivation :
                             H n : (τ1 , τ2 ) event H v : τ1
                                               H    emit n v : unit
      Par ailleurs, H () : unit.
                  e                                                e
      Nous avons ´galement H S. Comme le typage de emit nous a donn´ H                       n : (τ 1 , τ2 ) event
      et H v : τ1 , nous avons :
                                      H S + [v/n]
      Donc emit n v/S        ()/S + [v/n].
      Cas signal x default v1 gather v2 in e/S →ε e[x ← n]/S[(v1 , v2 , (false, v1 ), ∅)/n] : La
       e
      d´rivation de signal/in est de la forme :
                   H    v 1 : τ2   H   v 2 : τ1 → τ 2 → τ 2        H[x : (τ1 , τ2 ) event]   e:τ
                               H   signal x default v1 gather v2 in e : τ
80                                               5. Typage

     Comme H S et n ∈ Dom(S), nous avons n ∈ Dom(H). Prenons alors l’environnement
                                                         e                    a
     H = H[n : (τ1 , τ2 ) event]. En utilisant l’indiff´rence du typage vis-`-vis des hypoth`ses   e
     inutiles, nous avons H [x : (τ1 , τ2 ) event] e : τ . Par ailleurs, H n : (τ1 , τ2 ) event. Donc
     avec le lemme de substitution, nous avons :

                                         H     e[x ← n] : (τ1 , τ2 ) event

     Nous pouvons montrer simplement que H S[(v1 , v2 , (false, v1 ), ∅)/n]. Enfin comme l’ex-
     pression signal x default v1 gather v2 in e est expansive, nous avons :

           signal x default v1 gather v2 in e/S               e[x ← n]/S[(v1 , v2 , (false, v1 ), ∅)/n]

     Pour les autres cas, ou bien ce sont des cas de ML, ou bien ils se prouvent simplement
     comme le cas run.


        e                    e
   La d´monstration de la pr´servation du typage se termine en passant au contexte avec la
      ee
propri´t´ de croissance de .

Lemme 7 (Croissance de             )
Pour tout contexte,

                         e1 /S1       e2 /S2   implique Γ[e1 ]/S1      Γ[e2 ]/S2

 e
D´monstration :
   Soient H et τ tels que H Γ[e] : τ et H S. Montrons que H           Γ[e ] : τ et H   S
        e                                                           e
   par r´currence sur la structure du contexte Γ. Le cas le plus int´ressant est celui du
   let/and/in.

                                                 e
     Cas let x1 = Γ[e1 ] and x2 = e2 in e : Une d´rivation de typage de cette expression se
     termine par :

                                    H Γ[e1 ] : τ1 H e2 : τ2
                   H[x1 : Gen(H, (Γ[e1 ], e2 ), τ1 ); x2 : Gen(H, (Γ[e1 ], e2 ), τ2 )]   e:τ
                                  H      let x1 = Γ[e1 ] and x2 = e2 in e : τ

                    e      e
     Par l’hypoth`se de r´currence, nous avons e1 /S e1 /S .
     Si Γ[e1 ] est non-expansive, alors e1 est non-expansive et donc e1 est non-expansive. Ainsi
           e
     par d´finition de la relation        , nous avons H      Γ[e1 ] : τ1 et H    S et Γ[e1 ] est
                              e                                      e
     non-expansive. Par cons´quent, nous pouvons construire la d´rivation :

                                    H Γ[e1 ] : τ1 H e2 : τ2
                   H[x1 : Gen(H, (Γ[e1 ], e2 ), τ1 ); x2 : Gen(H, (Γ[e1 ], e2 ), τ2 )]   e:τ
                                  H      let x1 = Γ[e1 ] and x2 = e2 in e : τ

                                  u
     Donc nous avons dans le cas o` e1 n’est pas expansive :

              let x1 = Γ[e1 ] and x2 = e2 in e/S          let x1 = Γ[e1 ] and x2 = e2 in e/S
                    5.2. Preuve de sˆret´ du typage pour la r´duction →
                                    u e                      e                                      81

                                                 e     e
     Maintenant, si e1 est expansive, l’hypoth`se de r´currence nous donne un environnement
         e
     H ´tendant H tel que H           Γ[e1 ] : τ1 et H    S . De plus comme e1 est expansive,
     nous avons Gen(H, (Γ[e1 ], e2 ), τ1 ) = τ1 et Gen(H, (Γ[e1 ], e2 ), τ2 ) = τ2 . Ainsi en utilisant
            e                    a                  e                                 e
     l’indiff´rence du typage vis-`-vis des hypoth`ses inutiles, nous avons la d´rivation :

                        H     Γ[e1 ] : τ1   H   e 2 : τ2    H [x1 : τ1 ; x2 : τ2 ]   e:τ
                                H      let x1 = Γ[e1 ] and x2 = e2 in e : τ

                        u                              e
     Donc, dans le cas o` e1 est expansive, nous avons ´galement :

              let x1 = Γ[e1 ] and x2 = e2 in e/S           let x1 = Γ[e1 ] and x2 = e2 in e/S




5.2.2                               e
        Les formes normales bien typ´es sont des expressions de fin d’instant
   Pour d´montrer que les formes normales vis-`-vis de la r´duction → sont des expressions
           e                                      a           e
                                                                                             e
de fin d’instant, nous utilisons le lemme de progression. Il montre qu’une expression bien typ´e
         e
peut se r´duire, sinon c’est une expression de fin d’instant.
                                                                       e
   Afin de simplifier la preuve de ce lemme, les expressions instantan´es (0 e) sont trait´es e
 e e
s´par´ment.

Lemme 8 (Lemme de progression des expressions instantan´es)     e
Soit H un environnement qui ne lie aucune variable x mais uniquement des noms de signaux
n. Supposons H e : τ , H S et 0 e. Alors, ou bien e est une valeur, ou bien il existe e et
S tels que e/S → e /S .

 e
D´monstration :
                             e                                                e
   Les expressions instantan´es correspondent aux expressions ML. Par cons´quent, la preuve
            e                                    e
   est la mˆme que pour ML. Elle se fait par r´currence sur la structure de e et par cas sur
                                    `                 u                     e
   e sachant que nous n’avons pas a traiter les cas o` l’expression e est r´active (1 e).
           e                            ee
   Cette d´monstration utilise la propri´t´ de la forme des valeurs selon leur type qui montre
   que le type d’une valeur conditionne sa structure (constante, fonction, paire, processus, ...).


Lemme 9 (Lemme de progression)
Soit H un environnement qui ne lie aucune variable x mais uniquement des noms de signaux
n. Supposons H e : τ , H S et k e. Alors, ou bien e est une expression de fin d’instant, ou
bien il existe e et S tels que e/S → e /S .

 e
D´monstration :
       e                         e
   La d´monstration se fait par r´currence sur la structure de e et par cas sur e.

                                  e e                                              e
     Cas 0 e : Avec le lemme pr´c´dent de progression des expressions instantan´es, nous
                                e
     savons que soit e peut se r´duire, soit e est une valeur. Donc si c’est une valeur c’est
     e                                                                        e
     ´galement une expression de fin d’instant car nous pouvons appliquer la r´duction :

                                                S   v →eoi v
82                                                5. Typage

     Cas pause : Cette expression est une expression de fin d’instant car nous pouvons appli-
              e
     quer la r`gle :
                                       O pause →eoi ()

     Cas run e : On a alors :

                                    H       e : τ process                     0       e
                                                                et
                                        H     run e : τ                   1       run e

                                                                     e e
     Si e n’est pas une valeur, nous pouvons appliquer le lemme pr´c´dent. Ainsi nous savons
                     e                           e                                e
     que e peut se r´duire et en appliquant la r`gle de contexte, run e peut se r´duire.
     Si e est une valeur, son type garantit que c’est un processus. Donc l’expression e est de la
                             e       e
     forme process e . La r`gle de r´duction du run s’applique :

                                        run (process e )/S →ε e /S


     Cas present e then e1 else e2 : On a alors :

       H    e : (τ, τ ) event   H       e1 : τ   H     e2 : τ                             0        e       1    e1   1   e2
                                                                     et
            H    present e then e1 else e2 : τ                                1       present e then e1 else e2

                                                           e                                 e
     Si e n’est pas une valeur, en appliquant le lemme de r´duction des expressions instantan´es,
                             e                      e
     il vient que e peut se r´duire. Donc avec la r`gle de contexte, present e then e 1 else e2
               e
     peut se r´duire.
                                                                                   e
     Si e est une valeur, comme c’est une expression de type (τ, τ ) event, c’est n´cessairement
     un signal n. Il y a alors deux cas :
     – Soit n ∈ S, et nous pouvons appliquer la r`gle de r´duction en tˆte de present :
                                                    e        e            e

                                 present n then e1 else e2 /S →ε e1 /S

     – Soit n ∈ S, et dans ce cas si O = next(S), nous savons que n ∈ 0. Nous avons donc une
                                          e
       expression de fin d’instant car la r`gle suivante s’applique :

                                                          n∈O
                                O       present n then e1 else e2 →eoi e2

                                  e
     Cas do e1 when e : Les hypoth`ses nous donnent :

                     H    e : (τ1 , τ2 ) event     H      e1 : τ                      0        e       1       e1
                                                                      et
                            H    do e1 when e : τ                                 1           do e1 when e

                                                  e
     Si e n’est pas une valeur, nous pouvons r´duire l’expression do e1 when e en utilisant le
               e e             e
     lemme pr´c´dent et la r`gle de contexte.
                                                  e                                         e
     Si e est une valeur, c’est un signal n. Nous ´tudions les deux cas en fonction de la pr´sence
     de n :
                    5.3. Pr´servation du typage pour la r´duction →eoi
                           e                             e                                   83

      – Si n ∈ S, nous appliquons l’hypoth`se de r´currence. Donc soit e1 peut ˆtre r´duit et
                                              e       e                           e     e
                                     e                                       e
        dans ce cas en utilisant la r`gle de contexte du when, nous pouvons r´duire l’expression
        do e1 when e. Soit e1 est une expression de fin d’instant et dans ce cas si e1 est une
                                      e
        valeur, nous appliquons la r`gle :

                                        do v when n/S →ε v/S

        si e1 n’est pas une valeur et O = next(S), alors do e1 when e est une expression de fin
        d’instant :
                                        n ∈ O O e1 →eoi e1
                                 O    do e1 when n →eoi do e1 when n
      – Si n ∈ S et O = next(S), alors do e1 when e est une expression de fin d’instant :

                                                 n∈O
                                 O    do e1 when n →eoi do e1 when n

      Pour les autres cas, nous pouvons utiliser des raisonnements similaires.


                                           e e         u e               e  c             ee
    Nous pouvons terminer la preuve du th´or`me de sˆret´ du typage en ´non¸ant la propri´t´
                                     ee              e
sur les formes normales. Cette propri´t´ est une cons´quence directe du lemme de progression.

                                           e
Lemme 10 (Les formes normales bien typ´es sont des expressions de fin d’instant)
Si T C e : τ et k e et e est en forme normale vis-`-vis de →, alors e est une expression de
                                                  a
fin d’instant.


5.3     Pr´servation du typage pour la r´duction →eoi
          e                             e
                                                       e            e                     e
   Comme nous l’avons vu chapitre 4.1.3 (page 68), la r´action compl`te d’un instant est d´finie
par :
                      e/S → e /S O = next(S ) O e →eoi e
                                         e/S ⇒ e /S
    Nous venons de montrer avec la preuve de sˆret´ du typage de → que si e/S → e /S alors
                                                u e
il existe un environnement de typage H tel que H S et H e : τ et O e →eoi e avec
O = next(S ) . Par ailleurs, nous savons que si H S alors H O. Donc pour prouver que la
 e             e                  e                              e             e e
r´action compl`te d’un instant pr´serve le typage, il nous faut d´montrer le th´or`me suivant :

Th´or`me 4 (Pr´servation du typage par r´duction →eoi )
   e e         e                           e
Si H S et O = next(S) et O e →eoi e alors e/S e /S.

 e
D´monstration :
                   e        e                            e           e
   La preuve proc`de par r´currence sur la taille de la d´rivation d’´valuation. On raisonne
   par cas sur l’expression e.
   En examinant chacun des cas, nous pouvons montrer que si O e →eoi e et que e est
   non-expansive alors e est non-expansive. Regardons maintenant ce qui ce passe au niveau
   des types.
84                                                5. Typage

     Cas v : Par hypoth`ses, H
                       e                   v : τ et O            v →eoi v. Donc nous avons directement
     H v : τ.
     Cas pause : Par hypoth`ses, H
                             e           pause : unit et O                         pause →eoi (). Par ailleurs
                                e
     H () : unit ce qui est le r´sultat attendu.
                            e
     Cas e1 ;e2 : Par hypoth`ses,

                      H     e 1 : τ1     H    e 2 : τ2                    O     e1 →eoi e1
                                                            et
                            H       e1 ;e2 : τ2                    O       e1 ;e2 →eoi e1 ;e2

                              e    e
     En appliquant l’hypoth`se de r´currence, nous avons H                          e1 : τ1 . Nous pouvons donc
                    e
     construire la d´rivation :
                                    H e 1 : τ1 H e 2 : τ2
                                                  H      e1 ;e2 : τ2

                                               e
     Cas present n then e1 else e2 : Par hypoth`ses,

                            H       n : (τ, τ ) event       H     e1 : τ       H     e2 : τ
                                    H     present n then e1 else e2 : τ

                                                         n∈O
                                O       present n then e1 else e2 →eoi e2
     Donc nous avons directement H           e2 : τ .
                                                                                   e
     Cas let x1 = e1 and x2 = e2 in e : La preuve est directe en utilisant l’hypoth`se de
      e
     r´currence et le lemme de croissance de .
                                                                                     e
     Cas do e1 until n(x) -> e2 done : Nous distinguons deux cas en fonction de la pr´sence
     de n dans l’environnement :
     – Si n ∈ S, nous utilisons l’hypoth`se de r´currence.
                                        e       e
     – Si n ∈ S, par hypoth`ses
                             e

                        H       n : (τ1 , τ2 ) event      H      e1 : τ       H[x : τ2 ]   e2 : τ
                                    H     do e1 until n(x) -> e2 done : τ

                                                  O(n) = (true, v)
                          O      do e1 until n(x) -> e2 done →eoi e2 [x ← v]
       Avec H n : (τ1 , τ2 ) event et l’hypoth`se H O, nous avons H O(n) : bool × τ2 et
                                              e
       donc H v : τ2 . Maintenant avec H[x : τ2 ] e2 : τ , nous pouvons appliquer le lemme
       de substitution et donc obtenir :

                                                  H      e2 [x ← v] : τ

                                                   e       e
     Cas do e when n : Il suffit d’appliquer l’hypoth`se de r´currence.
                    5.3. Pr´servation du typage pour la r´duction →eoi
                           e                             e                                 85

 e   e
R´sum´
                                    e   e        e                                 e
    Dans ce chapitre, nous avons pr´sent´ le syst`me de type du langage. Ce syst`me est une
                                                      e                  u e
extension conservative de celui de ML. La particularit´ de la preuve de sˆret´ du typage vient
       e                                                                       e
de la d´finition de la forme normale. En effet, une forme normale ne doit pas ˆtre une valeur
                          u                                                e     e
pour que le typage soit sˆr, il faut que ce soit une expression qui peut ˆtre r´duite par la
r´duction →eoi .
 e
                                      e
                                Troisi`me partie

                           Ordonnancement

6         e                                      e     e
    Une s´mantique efficace pour le mod`le r´actif I : Glouton                                                                                   89
              e              e
    6.1 Les cl´s d’un interpr`te efficace . . . . . . . . . . . . . . . . . .                           .   .   .   .   .   .   .   .   .   .    89
                                      e
    6.2 Les groupes : le format d’ex´cution de Glouton . . . . . . . .                                .   .   .   .   .   .   .   .   .   .    92
                     e
        6.2.1 La d´finition des groupes . . . . . . . . . . . . . . . . .                              .   .   .   .   .   .   .   .   .   .    92
        6.2.2 Traduction de ReactiveML vers les Groupes . . . . . . .                                 .   .   .   .   .   .   .   .   .   .    94
        ´
    6.3 Evaluation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .                        .   .   .   .   .   .   .   .   .   .    97
                   e
        6.3.1 Ex´cution d’un programme . . . . . . . . . . . . . . . .                                .   .   .   .   .   .   .   .   .   .    97
                   e
        6.3.2 Ex´cution d’une instruction . . . . . . . . . . . . . . . .                             .   .   .   .   .   .   .   .   .   .    99
                 e                e                       e
        6.3.3 S´mantique sans ´chappement de port´e . . . . . . . . .                                 .   .   .   .   .   .   .   .   .   .   101
                                           o
    6.4 Ajout des constructions de contrˆle . . . . . . . . . . . . . . . .                           .   .   .   .   .   .   .   .   .   .   103
        6.4.1 La suspension . . . . . . . . . . . . . . . . . . . . . . . .                           .   .   .   .   .   .   .   .   .   .   103
                      e
        6.4.2 La pr´emption . . . . . . . . . . . . . . . . . . . . . . .                             .   .   .   .   .   .   .   .   .   .   106
    6.5 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . .                          .   .   .   .   .   .   .   .   .   .   108

7         e
    Une s´mantique efficace pour le mod`le       e        e
                                                      r´actif II : Lk                                                                         111
    7.1 Le langage avec continuation Lk . . . . .     . . . . . . . . . .                 .   .   .   .   .   .   .   .   .   .   .   .   .   111
         e
    7.2 S´mantique . . . . . . . . . . . . . . . .    . . . . . . . . . .                 .   .   .   .   .   .   .   .   .   .   .   .   .   113
                                         o
    7.3 Ajout des constructions de contrˆle . . .     . . . . . . . . . .                 .   .   .   .   .   .   .   .   .   .   .   .   .   116
    7.4 Conclusion . . . . . . . . . . . . . . . .    . . . . . . . . . .                 .   .   .   .   .   .   .   .   .   .   .   .   .   122

8   Implantation                                                                                                                            125
    8.1 Compilation vers Lk . . . . . . . . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   . 125
    8.2 Implantation des combinateurs . . . . . . .       .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   . 126
    8.3 Implantation en Ocaml . . . . . . . . . . .       .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   . 129
                                          e
    8.4 Ajout de la suspension et de la pr´emption        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   . 135
                                       e e
    8.5 Implantation sous forme API g´n´rique . .         .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   . 136
    8.6 Conclusion . . . . . . . . . . . . . . . . . .    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   . 140
                                             Chapitre 6

              e
         Une s´mantique efficace pour le
                e  e
           mod`le r´actif I : Glouton

                        e e               e             e                              e
     Dans la partie pr´c´dente, les deux s´mantiques d´crivent assez simplement la r´action d’un
                                                                                    e
programme, mais ne donnent pas d’indications pour l’implantation d’un interpr`te efficace. Le
                                                      e                           a
but de cette partie est d’effectuer le passage de ces s´mantiques intuitives jusqu’` l’implantation.
                      e         e
     Ce chapitre pr´sente la s´mantique de Glouton, une implantation de Junior que nous
        e e                                                                              e
avons r´alis´e avant de travailler sur ReactiveML. Le nom Glouton vient de l’id´e de faire
                                                                            e e
un ordonnancement glouton des calculs. Comme dans la programmation ´v´nementielle, les ex-
                          e e                 e
pressions en attente d’´v´nements sont post´es et un ordonnanceur les traite. Ce travail s’inspire
                                                                                  e
de Simple l’implantation faite par Laurent Hazard [55]. Simple est la premi`re implantation
         e e                    e                         e
du mod`le r´actif qui a utilis´ des files d’attente associ´es aux signaux. Ces files d’attente per-
              e               e                                               e       e e
mettent de d´clencher l’ex´cution des actions seulement quand elle peuvent ˆtre ex´cut´es. C’est
    e           e
l’id´e d’une ex´cution paresseuse sans attente active des signaux.
                      e               e                 `
     La particularit´ de nos interpr`tes par rapport a d’autres implantations efficaces comme
Storm [100] et Reflex [28] est de destructurer l’arbre de syntaxe abstraite du programme
                    e                         ` e
pour avoir un acc`s direct aux instructions a ex´cuter. Mais cette approche a pour contrepartie
de rendre plus difficile l’implantation des constructions de bloc comme la suspension et la
   e
pr´emption.
           e                          ee                                               ee
     Les id´es et l’implantation ont ´t´ faites pour Junior. Ce travail a d’ailleurs ´t´ compar´  e
                                     e   e                   e
aux autres implantations du mod`le r´actif dans deux th`ses ([1, 28]). Mais pour l’unit´ du   e
                                    e            e
document, nous trouvons plus int´ressant de d´crire cette formalisation en ReactiveML.


6.1              e              e
           Les cl´s d’un interpr`te efficace
                                                          e
    Une partie importante des travaux sur l’approche r´active porte sur l’implantation d’in-
     e                                                 u                   e
terpr`tes efficaces [55, 100, 20, 28, 40]. Dans [1], Ra´l Acosta-Bermejo r´capitule un certain
                  e                      `          e
nombre de caract´ristiques communes a ces interpr`tes.
                                                                          ıve      e e
    Le point principal est l’attente des signaux. Dans une implantation na¨ du mod`le r´actif
                                                  e                          e
comme Rewrite [56], toutes les branches parall`les du programme sont activ´es successivement
           `              a
de gauche a droite jusqu’` l’obtention d’un point fixe. Ainsi, dans le programme suivant, l’ex-
                                           e                              e    `         e
pression await immediate s1 est activ´e deux fois avant de pouvoir se r´duire a la troisi`me
activation 1.

  1
      C’est l’exemple classique de la cascade inverse.


                                                         89
90                                                    6. Glouton

         await immediate s1 || await immediate s0; emit s1 || emit s0

                                                         s0
                                                     − − − − −→
                                                     −− − − − −

         await immediate s1 || await immediate s0; emit s1

                                                        s0, s1
                                                     − − − − −→
                                                     −− − − − −

         await immediate s1
                                                                         e
    Dans Rewrite, le fait que await immediate s1 ne puisse pas r´agir tant que le signal s1
         e ee                    e `                                   e                   e    e
n’a pas ´t´ ´mis n’est pas utilis´. A chaque tour d’activation la premi`re branche est test´e mˆme
                         e
si elle ne peut pas se r´duire. Dans ce cas, l’implantation fait de l’attente active. La solution
        e                                                   e
propos´e par Laurent Hazard est d’enregistrer la premi`re branche dans une file d’attente de
              e                                          e                                    e
s1 et de la r´activer uniquement lorsque le signal est ´mis. Ainsi une instruction est activ´e au
                                                     `
plus deux fois par instant. Ceci correspond donc a une attente passive : un calcul est mis en
                                     e                                 e
attente sur un signal et sera activ´ seulement lorsque le signal sera ´mis.
    ´                                    e
    Etudions la variante non-instantan´e de la cascade inverse [1] :
  await s1 || await s0; emit s1 || emit s0
                   e
Ici, s1 n’est pas ´mis au premier instant mais au second. En fonction des implantations, les
                                e                 `
listes d’attente sont conserv´es d’un instant a l’autre ou pas. Nous distinguons donc l’attente
                                 e e
intra-instant de l’exemple pr´c´dent, de l’attente inter-instants de cet exemple.
    Si l’ordonnancement est parfait (on n’active jamais plus d’une fois une expression), la gestion
                                    u          u               e e
des files d’attente ajoute bien sˆr un surcoˆt. Mais en g´n´ral, il est toujours pertinent d’im-
                                                  e
planter l’attente intra-instant dans un interpr`te. Le choix n’est pas aussi simple pour l’attente
                              e                              e
inter-instants car elle interf`re avec la suspension et la pr´emption. Dans l’exemple suivant, l’ex-
                                    e     e     e        e               e
pression await s1 ne peut pas ˆtre d´bloqu´e par l’´mission de s1 mˆme si elle est enregistr´e    e
dans la file d’attente de s1 car s0 est absent au second instant.
  do await s1 when s0 || emit s0; pause; emit s1
                         e
Dans certain cas, les m´canismes mis en place pour avoir de l’attente passive inter-instants
         e           u
peuvent ˆtre plus coˆteux que d’activer une fois par instant chaque instruction. Une des diffi-
    e                                      e
cult´s est qu’un choix d’implantation peut ˆtre bon ou mauvais en fonction de la structure du
                 e              e
programme et mˆme de ses entr´es.
                                                                      e
   Un autre point mis en avant dans [1] est l’utilisation du parall`le n-aire. Par exemple, si
          e                                 e             ee                           e `
on veut ex´cuter trois expressions en parall`le, il est pr´f´rable d’utiliser un parall`le a trois
                         e
branches que deux parall`les binaires.


                                   ||                                              || W
                                  } eee                                        Õ      WW
                                }}     ee                                    ÕÕ         WW
                              }}         ee                                ÕÕ             WW
                          ~}}}            e2                           ÒÕÕ                 (
                     e1          e2             e3                 e1                           || W
                                                                                           ÕÕ      WW
                                                                                         ÕÕ          WW
                                                                                        Õ              WW
                                                                                     ÒÕÕ                 (
                                                                               e2                        e3
                                         e              e
                              6.1. Les cl´s d’un interpr`te efficace                                  91

                 e              e             `                                             e
L’argument utilis´ est que cela ´vite d’avoir a parcourir la structure du terme pendant l’ex´cution.
                                                                                 e
Malheureusement, il est assez naturel en ReactiveML d’avoir des parall`les binaires. Par
                        e                 e                              `
exemple le processus r´cursif add qui ex´cute un nouveau processus a chaque fois que le signal
             e         e                       e
new_proc est ´mis, cr´e un peigne de parall`les :
  let rec process add new_proc =
    await new_proc(p) in
    run p
    ||
    run (add new_proc)
  val add : (’a, ’b process) event -> unit process
                                                                         `      e
La solution que nous proposons est de casser la structure du terme a l’ex´cution. Ainsi, il
                      e         `             ` e
y a toujours un acc`s direct a l’expression a ex´cuter. Au lieu de manipuler une expression,
        e                                              ` e                 e
l’intepr`te travaille avec des ensembles d’expressions a ex´cuter en parall`le.
                                e e                            e                                e
    Pour faire l’optimisation pr´c´dente, il faut que le parall`le soit associatif. Si le parall`le est
                                                  e
en plus commutatif, il y a une plus grande libert´ dans l’ordonnancement ce qui facilite l’implan-
                                                  e
tation. En SugarCubes, la composition parall`le (merge) n’est pas comme en ReactiveML.
                                                    e e
Elle garantit que la branche gauche est toujours ex´cut´e avant la branche droite au cours d’une
 e                     ee
r´action. Cette propri´t´ ajoute des contraintes dans l’implantation des ordonnanceurs et donc
                                 u `     e
se traduit souvent par un surcoˆt a l’ex´cution.
                 e e                    ıtre        e
    Enfin, le mod`le r´actif fait disparaˆ des probl`mes d’ordonnancement des langages asyn-
                                                       e
chrones. Par exemple, le choix de l’ordonnancement a tr`s peu d’influence sur la consommation
  e
m´moire ce qui n’est pas vrai dans le cadre asynchrone. Illustrons cela sur un exemple simple.
  e                                        e
D´finissons un processus producteur qui ´met dix entiers et un processus consommateur qui les
                                               e    e                        c
affiche. En ReactiveML, le producteur peut ˆtre ´crit d’au moins deux fa¸ons. La premi`re   e
e                                  e                     e
´met toutes les valeurs dans le mˆme instant, la seconde ´met une valeur par instant :
  let process producer1 s =
    for i = 1 to 10 do
      emit s i
    done

  let process producer2 s =
    for i = 1 to 10 do
      emit s i;
      pause
    done

  let consumer s =
    loop
      await s(x) in List.iter print_int x
    end
                                                    e          e                         e
Ces deux producteurs ont des consommations de m´moire diff´rentes. Le premier doit m´moriser
les dix entiers pendant un instant, alors que le second doit garder un seul entier par instant. Le
                                                         e `           e
programmeur peut choisir l’implantation la plus adapt´e a son probl`me. Dans un cadre asyn-
                                  e             e
chrone, c’est l’ordonnanceur qui ´quilibre l’ex´cution entre le producteur et le consommateur.
92                                                    6. Glouton

                                                                         `
En fonction de l’ordonnancement, un programme asynchrone peut donc avoir a stocker entre
un et dix entiers.




6.2                                      e
             Les groupes : le format d’ex´cution de Glouton

6.2.1             e
              La d´finition des groupes

        e                                     e
    La s´mantique de Glouton n’est pas donn´e directement sur le source ReactiveML, mais
                                                                                   e
sur un format que nous appelons les Groupes. Ce format est fait pour faciliter l’ex´cution efficace
                             e
des programmes. Les deux id´es fondatrices de ce format sont l’utilisation de continuations et
                                                     e
le regroupement dans des groupes des branches parall`les qui doivent se synchroniser avant de
           e
pouvoir ex´cuter leur continuation.
       a `         e                                                                 e     e e
    Grˆce a la repr´sentation avec continuations, nous savons toujours ce qui doit ˆtre ex´cut´
   e                                               e
apr`s une instruction. Ainsi, un programme peut ˆtre vu comme un ensemble de suites d’ins-
                                           o                          ` e
tructions et un ensemble de points de contrˆle indiquant les branches a ex´cuter. Illustrons cela
sur un exemple 2 . Nous trouvons a gauche le programme source et a droite sa repr´sentation
                                  `                                  `                 e
                       e
dans une forme simplifi´e des groupes :



           emit s1;                       emit s11          await s14         run p8      await s2(x)10
           pause;
           (run p                                                                               
            ||                             pause2          let x = 25         term9          print x11
            await s2(x) in
            print x)                                                                                 
           ||                           split(8, 10)3      emit s2 x6                          term12
           await s1;
           let x = 2 in                                               
           emit s2 x                                           term7




                     e                                                          e
    Les points d’entr´e de ce programme sont les instructions 1 et 4 (le num´ro des instruc-
               e                                            e              e
tions est donn´ en indice). L’instruction split(8, 10) repr´sente le parall`le qui est imbriqu´e
                                e                                    o
dans la branche gauche. Son ex´cution donne deux points de contrˆle sur les instructions 8 et
                                                                e
10. Les instructions term indiquent la fin des branches parall`les. Nous constatons que cette
    e                                                                             `
repr´sentation casse la structure de l’arbre de syntaxe abstraite du programme. A la place, elle
              e                                          e
propose une s´quence d’instructions par branche parall`le.
                                                                e          e           e e
   Nous voulons maintenant ajouter l’instruction emit s3 en s´quence apr`s le bloc pr´c´dent.
                          e      e e                              e                       e
Cette instruction ne peut ˆtre ex´cut´e qu’une fois le bloc termin´. Afin de garder cette d´pen-


     2
                                          e
         Cet exemple ne calcule rien d’int´ressant, mais il permet de montrer la structure du programme.
                                                      e
                     6.2. Les groupes : le format d’ex´cution de Glouton                                 93

                                              e e
dance, nous mettons les suites instructions pr´c´dentes dans un groupe :
                                                                        
       emit s11         await s14       run p8    await s2(x)10         
      
                                                                        
                                                                         
      
                                                                        
                                                                         
      
                                                                        
                                                                         
                                                          
                                                                         
      
      
       pause                                                         
                                                                         
      
      
                 2     let x = 25        term9       print x11           emit s313
                                                                         
                                                                         
                                                                         
                                                                        
                                                                    3
                                                                      13
      
                                                                     
                                                                               
       split(7, 8)3
      
      
                       emit s2 x6                      term12
                                                                         
                                                                         
                                                                         
                                                                            term14
      
                                                                        
                                                                         
      
                                                                        
                                                                         
      
                                                                        
                                                                         
      
                                                                       
                                                                         
                           term7
                                                                        

La partie “ 3 13” du groupe indique qu’il faut ex´cuter trois instructions term pour terminer
                                                    e
     e
l’ex´cution du groupe et que sa continuation est l’instruction 13. Le chiffre 3 vient du fait qu’il
                          e
y a trois branches parall`les dans le bloc. La synchronisation de la terminaison n’est pas faite
`                         e                            e                      e
a la fin de chaque parall`le mais au moment de la s´quence. Un groupe d´finit donc un bloc
                            e e                                     e                       e
dont la continuation est ex´cut´e lorsque toutes les branches parall`les du bloc ont termin´ leur
   e
ex´cution.
       e           e
     Pr´cisons la d´finition des groupes (G) :
                                   cpt
                       G ::= {I          k}          I ::= ∅ | ti , I   k ::= (id, i)

On trouve trois informations dans un groupe : la liste des instructions num´rot´es I, cpt le
                                                                                 e e
                          e                                ` e                                 e
nombre de branches parall`les du groupe et k l’instruction a ex´cuter une fois le groupe termin´.
k est compos´ de id un nom de groupe et i le num´ro de l’instruction dans ce groupe 3 . Chaque
            e                                      e
groupe est donc associ´ a un nom dans un environnement G.
                      e`

                                              G ::= [G/id, ..., G/id]

Les instructions t dans les groupes sont les suivantes :

         t ::=       term | e | run e | await immediate x
                   | present x then k else k | split k k
                   | let x = e in (G, k)
                   | await x(x ) in (G, k)
                   | signal x default e gather e in (G, k)

         e ::=       x | c | (e, e) | λx.e | e e | rec x = e | let x = e in e | process(λx.G, k)
                   | pre e | pre ?e | emit e e | signal x default e gather e in e

                               `                           e
 L’instruction term correspond a la fin d’une branche parall`le. Une expression e est une expres-
               e                                e        e
sion instantan´e. Dans les expressions instantan´es, la d´finition de processus est un ensemble
                               e                        e                  e           e
de groupes et un point d’entr´e pour commencer l’ex´cution. Le param`tre x repr´sente la
continuation du processus.
    Les instructions await/immediate et run sont celles de ReactiveML. Pour l’instruction
                                                             e
present, dans les branches then et else, on donne le num´ro des instructions correspondant
  3
                        e e                                                                              e
    Dans les exemples pr´c´dents, nous avons omis les noms de groupes car chaque instruction avait un num´ro
unique.
94                                               6. Glouton

`                                                e e
a ces branches. L’instruction split est param´tr´e par ses deux continuations. Enfin, pour les
                                                                                        e
instructions qui sont des lieurs, le corps est un ensemble de groupes et un point d’entr´e.
                                                                                     e
    Nous pouvons remarquer que les instructions let/in et signal/in sont dupliqu´es car elles
                         e                  e
ont une forme instantan´e et une forme r´active.
                                                 e           e
    Ce format se rapproche des formats interm´diaires utilis´s pour la compilation de Esterel
                                                                              e
vers du logiciel (pas des circuits). Il se rapproche en particulier de ceux d´finis dans Saxo-
                                                   e
RT [32], GRC [89] ou CEC [38]. La grande diff´rence entre notre approche et la compilation
                                                                 `    e
d’Esterel est qu’en ReactiveML, l’ordonnancement est fait a l’ex´cution alors qu’en Este-
                                 `
rel, l’ordonnancement est fait a la compilation.
         e                                                     e
    La d´finition du format des groupes que nous avons donn´e correspond au noyau de Reac-
tiveML suivant :
          e ::=       x | c | (e, e) | λx.e | e e | rec x = e | process e | e;e
                    | e||e | present x then e else e | emit e e
                    | signal x default e gather e in e | await immediate x
                    | await x(x) in e | pause | let x = e in e | run e | pre e | pre ?e

          c ::=      true | false | () | 0 | . . . | + | - | . . .
                           e                                                    e
Ce noyau est un peu diff´rent de celui du chapitre 3. Afin de simplifier la pr´sentation nous
                                       e
ne traitons pas la suspension et la pr´emption pour le moment mais dans la seconde partie
                        e
du chapitre. Par cons´quent, nous ajoutons les constructions await au noyau pour expliquer
                                               ee
l’attente d’un signal. De plus, Glouton ayant ´t´ fait pour Junior, la terminaison de processus
                                                   e
ne rend pas de valeurs. Donc, nous avons remplac´ la construction let/and/in par e 1 ||e2 et
                                                                                   e
nous interdisons dans la construction let x = e1 in e2 que e1 soit une expression r´active. Nous
                            e
verrons chapitre 7 les cons´quences de ce choix.
Remarque :
                                             e             `           e
   Avoir la partie gauche du let/in instantan´e correspond a avoir la r`gle suivante dans la
   figure 3.2 page 48 :
                                       0 e 1 k e2
                                             k    let x = e1 in e2

                                                                                          `
    Enfin, dans ce noyau, les instructions qui testent les signaux s’appliquent uniquement a des
                            `                                                   e
noms de variables et pas a des expressions. Cette modification simplifie la pr´sentation de la
 e                  e                      e
s´mantique et ne r´duit pas l’expressivit´ du langage. En effet, on peut toujours calculer le
signal avant de le tester. Par exemple, l’expression await immediate e devient :

                                 let x = e in await immediate x

6.2.2    Traduction de ReactiveML vers les Groupes
    Nous ne faisons pas la traduction directement de ReactiveML vers les groupes, mais nous
                            e                                                            e
utilisons un format interm´diaire. Dans ce format, nous distinguons deux formes de s´quences.
           e                                     e                         e
La premi`re est la continuation qui permet d’ex´cuter une instruction apr`s l’autre. La seconde
                                                         e                        e
forme attend la terminaison de plusieurs branches parall`les avant de pouvoir ex´cuter la suite
                        e               o
du programme. Elle a ´galement un rˆle de synchronisation.
                                                   e                        o                 `
    Traditionnellement, c’est la composition parall`le qui joue un double rˆle. Elle permet a la
         e                       o                                                              e
fois de s´parer le point de contrˆle d’un programme en deux puis de le fusionner. Ici, le parall`le
                                                       e
                      6.2. Les groupes : le format d’ex´cution de Glouton                           95

                o        e                                                     e
va garder son rˆle de s´paration, mais pas celui de fusion. Nous laissons la s´quence synchroniser
la terminaison des branches parall`les.e
    Cette approche permet de factoriser les points de synchronisation. Par exemple dans l’ex-
                                            e
pression (e1 ||(e2 ||e3 ));e4 , si le parall`le synchronise la terminaison, il faut deux points de
                                         e
synchronisation alors que si c’est la s´quence qui synchronise, il n’en faut qu’un seul.
                        e
    Le langage interm´diaire que nous utilisons pour obtenir les groupes est le suivant :

           p   ::=      term | e.p | pause.p | present x then P else P.p
                      | signal x default e gather e in P.p | let x = e in P.p
                      | await immediate x.p | await x(x) in P.p | run e.p | P ||P

           P   ::=      p | P ;P

           e   ::=      x | c | (e, e) | λx.e | e e | let x = e in e | rec x = e | pre e | pre ?e
                      | process P | emit e e | signal e default e gather e in e

                  `
Le “.” correspond a la continuation et le “;” permet la synchronisation.
   La fonction de traduction de ce format vers celui des groupes a la forme suivante :

                                       T r(P, id, i) = (G, I, k, cpt, i )

                            `
   – P est le programme a traduire ;
   – id est le nom du groupe dans lequel P est traduit ;
                   e
   – i est le num´ro de la prochaine instruction de P ;
   – G est l’environnement contenant les groupes cr´´s par la traduction ;
                                                      ee
   – I est la liste des instructions a ajouter dans id ;
                                     `
                           e
   – k est le point d’entr´e du programme ;
                                           e     ee
   – cpt est le nombre de branches parall`les cr´´es par P ;
                                   e
   – i est le compteur pour num´roter la prochaine instruction du groupe.
                                        e      e                                    ´
   Cette fonction de traduction est d´finie r´cursivement sur la structure du terme. Etudions
chacun des cas.

 T r(term, a, i) = ([ ], termi , (a, i), 1, i + 1)

                                        u              e                                    e
L’instruction term se traduit en termi o` i est le num´ro d’instruction. La traduction ne cr´e
                                                  e          e
pas de sous-groupes et a une seule branche parall`le. Le num´ro de la prochaine instruction a`
traduire est i + 1.

 T r(e.p, a, i) =
    let (G, I, k, cpt, i ) = T r(p, a, i + 1) in
    let e = T rM L (e) in
    (G, (ei , I), (a, i), cpt, i )

                                      `                e
Pour traduire e.p, nous traduisons p a partir du num´ro d’instruction i + 1, puis nous traduisons
                        `           e                                          e
e en e . Nous donnons a e le num´ro i pour que sa continuation soit la premi`re instruction de
       e                                e                                                     e
p. Le r´sultat de la traduction est le r´sultat de la traduction de p auquel nous avons ajout´ e i
                        u
comme instruction et o` (a, i) est le nouveau point d’entr´e.e
                                                           e                 e
    La fonction T rM L laisse les expressions ML inchang´es. Le seul cas int´ressant est celui de
la traduction de processus :
96                                                    6. Glouton

 T rM L (process P ) =
    let a = f resh() in
    let (G, I, k, cpt, i) = T r(P, a, 1) in
    process(λx.G[{I cpt x}/a], k)
                     e                                                                   `
La fonction f resh cr´e un nouveau nom de groupe a et P est traduit dans ce groupe. A partir
    e                                                 ee              e e
du r´sultat de la traduction de P , le groupe a est cr´´. Il est param´tr´ par sa continuation x.
 T r(pause.p, a, i) =
    let (G, I, k, cpt, i ) = T r(p, a, i + 1) in
    (G, ((await immediate eoi)i , I), (a, i), cpt, i )
                                             e                          e
pause se traduit par l’attente d’un signal sp´cial : eoi. Ce signal est ´mis lorsque le programme
              e             e
ne peut plus r´agir pour pr´parer la phase de traitement de fin d’instant.
 T r(run e.p, a, i) =                                      T r(await immediate x.p, a, i) =
   let (G, I, k, cpt, i ) = T r(p, a, i + 1) in              let (G, I, k, cpt, i ) = T r(p, a, i + 1) in
   let e = T rM L (e) in                                     (G, ((await immediate x)i , I), (a, i), cpt, i )
   (G, (run e i , I), (a, i), cpt, i )
                                                                         e e
     Les traductions de await/immediate et run sont comme pour les cas pr´c´dents.
 T r(present x then P1 else P2 .p, a, i) =
    let (G, I, k, cpt, i ) = T r(p, a, i + 1) in
    let b = f resh() in
    let (G1 , I1 , k1 , cpt1 , i1 ) = T r(P1 , b, 1) in
    let G1 = {I1 cpt1 k} in
    let c = f resh() in
    let (G2 , I2 , k2 , cpt2 , i2 ) = T r(P2 , c, 1) in
    let G2 = {I2 cpt2 k} in
    ([G1 /b, G2 /c] ∪ G ∪ G1 ∪ G2 , ((present x then k1 else k2 )i , I), (a, i), cpt, i )
Pour traduire present, nous traduisons la continuation p dans le groupe a. Cette traduction
                            e
nous donne un point d’entr´e k. Nous traduisons ensuite les deux branches dans deux groupes
   e                                e                           `           a
diff´rents. Ces groupes prennent le mˆme k comme continuation. A partir de l`, nous construi-
sons l’instruction present.
 T r(P1 ||P2 , a, i) =
    let (G1 , I1 , k1 , cpt1 , i1 ) = T r(P1 , a, i + 1) in
    let (G2 , I2 , k2 , cpt2 , i2 ) = T r(P2 , a, i1 ) in
    ((G1 , G2 ), ((split k1 k2 )i , I1 , I2 ), (a, i), cpt1 + cpt2 , i2 )
                          e
Pour la composition parall`le, les deux branches sont traduites et nous ajoutons une instruction
                                                                     ` e
split pour pouvoir les commencer. Le nombre d’instructions term a ex´cuter (cpt 1 + cpt2 ) est
e    `
´gal a la somme de celles des deux branches.
 T r(P1 ;P2 , a, i) =
    let (G2 , I2 , k2 , cpt2 , i2 ) = T r(P2 , a, i) in
    let b = f resh() in
    let (G1 , I1 , k1 , cpt1 , i1 ) = T r(P1 , b, 1) in
    let G1 = {I1 cpt1 k2 } in
    ([G1 /b] ∪ G1 ∪ G2 , I2 , k1 , cpt2 , i2 )
                                                 ´
                                            6.3. Evaluation                                     97

                  e                   c
Pour traduire la s´quence, nous commen¸ons par traduire la branche droite, puis la branche
                                                                          e
gauche dans un nouveau groupe. Ce nouveau groupe prend k2 (le point d’entr´e de la branche
droite) comme continuation.

 T r(let x = e in P.p, a, i) =
    let (G, I, k, cpt, i ) = T r(p, a, i + 1) in
    let e = T rM L (e) in
    let b = f resh() in
    let (Gb , Ib , kb , cptb , ib ) = T r(P, b, 1) in
    let G = {Ib cptb k} in
    (G, ((let x = e in ([G/b] ∪ Gb , kb ))i , I), (a, i), cpt, i )

                                                                                  e
Pour le let/in, nous traduisons le corps dans un groupe pour marquer la port´e de x. Le
                 e
groupe est associ´ au let pour pouvoir faire la substitution de x par sa valeur au moment de
  e
l’´valuation.

 T r(signal x default e1 gather e2 in P.p, a, i) =
    let (G, I, k, cpt, i ) = T r(p, a, i + 1) in
    let e1 = T rM L (e1 ) in
    let e2 = T rM L (e2 ) in
    let b = f resh() in
    let (Gb , Ib , kb , cptb , ib ) = T r(P, b, 1) in
    let G = {Ib cptb k} in
    (G, ((signal x default e1 gather e2 in ([G/b] ∪ Gb , kb ))i , I), (a, i), cpt, i )

                                    e
La traduction de signal utilise la mˆme technique de traduction que le let/in.


6.3     ´
        Evaluation
6.3.1      e
         Ex´cution d’un programme
             e                                 e                      e
    La strat´gie d’ordonnancement que nous pr´sentons est une strat´gie gloutonne. Nous l’avons
 e e
r´alis´e en essayant de comprendre les travaux de Laurent Hazard dont il existe une implantation
                                     e
mais pas de description. Elle est bas´e sur l’utilisation de files d’attente. Ainsi, les expressions
                 e e               e e                                e
en attente d’un ´v´nement sont ex´cut´es uniquement lorsqu’il est ´mis.
    Dans cette s´mantique, un programme est repr´sent´ par son code G, l’ensemble des ins-
                 e                                    e    e
tructions C a ex´cuter dans l’instant courant et l’ensemble des instructions W en attente. Le
              ` e
               e
principe de l’´valuation d’un programme est le suivant :
  1. Les instructions pr´sentes dans C sont prises une a une pour ˆtre trait´es. Si l’instruction
                         e                               `           e        e
     trait´e teste un signal qui est absent, elle est enregistr´e dans l’ensemble W. Par contre,
           e                                                   e
                  e        e            e              e e                                e
     si elle peut ˆtre enti`rement trait´e, elle est ex´cut´e et sa continuation est ajout´e dans
     C pour ˆtre ex´cut´e dans le mˆme instant. Enfin, l’´mission d’un signal fait passer les
              e      e e              e                       e
     instructions en attente dans W dans l’ensemble C.
  2. Une fois que toutes les instructions de C ont ´t´ trait´es (C = ∅), la fin d’instant peut ˆtre
                                                   ee       e                                 e
      e    e                                              e                          e
     d´clar´e. Le signal eoi (End Of Instant) est alors ´mis et les instructions pr´sentes dans
     W sont trait´es pour construire le nouvel ensemble C a ex´cuter a l’instant suivant.
                  e                                           ` e        `
98                                               6. Glouton

           e                                        e             e
   Nous d´finissons maintenant formellement ces deux ´tapes de la r´action d’un programme
          e
avec des r`gles de la forme suivante :

               S, G, W    C     S,G,W                et        S, G, W       eoi   S, G , W   C

C est un ensemble de couples : (nom de groupe, num´ro d’instruction). W est une fonction qui
                                                      e
        `                               e
associe a chaque signal la liste des num´ros d’instruction qui sont en attente.

                         C ::= ∅ | (id, i), C                W ::= [. . . , C/n, . . .]

                                                                 e  e
Pour les environnements de signaux S, nous reprenons la mˆme d´finition que dans le cha-
                             `
pitre 3.3.1 (page 49). Donc a chaque signal n, on associe dans l’environnement : une valeur
      e                                              e e
par d´faut, une fonction de combinaison, le statut pr´c´dent du signal et le multi-ensemble des
        e
valeurs ´mises pendant l’instant.
             e e             e            e              e
    La premi`re ´tape de la r´action est d´finie par les r`gles :

                                      S, G, W         ∅       S, G, W

                    G(a, i) = t  S, G, W ta −→ S , G , W
                                          i              C
          W , C = wakeU p(S#S , W )    S,G,W    C∪C ∪C     S ,G ,W
                                S, G, W         (a, i), C      S ,G ,W

          e    e                                              ` e       `
La premi`re r`gle indique que si l’ensemble des instructions a ex´cuter a l’instant courant est
                               e
vide alors l’instant est termin´.
   Pour la seconde r`gle, le code de l’instruction (a, i) est r´cup´r´ dans G avec la fonction
                       e                                       e   ee
G(a, i). Cette fonction est d´finie par :
                             e
                                                       cpt
                          Si G(a) = {..., ti , ...           k} alors G(a, i) = t

    Puis, cette expression est ex´cut´e avec la r´action S, G, W ta −→ S , G , W
                                 e e             e                  i                  C d´finie
                                                                                           e
section 6.3.2.
                                                                  e
    Ensuite avec la fonction wakeU p, toutes les instructions qui ´taient en attente d’un signal
qui a ´t´ ´mis pendant la r´action de t sont sorties de W . L’op´ration S#S d´finit l’ensemble
      eee                   e                                   e               e
                                    e                                      e
N contenant tous les signaux qui ´taient absents dans S et qui sont pr´sents dans S . Ainsi
pour tout n ∈ Dom(S ), alors

                                 n ∈ S#S          ssi n ∈ S et n ∈ S

                           e                                                   ee e
La fonction wakeU p qui d´bloque les instructions en attente d’un signal qui a ´t´ ´mis est
 e      e
d´finie r´cursivement par :

 wakeU p(∅, W) = W, ∅

 wakeU p({n} · N, W) =
   let W , C = wakeup(N, W) in
   let C = W (n) in
   let W = W \n in
   W , (C ∪ C )
                                                ´
                                           6.3. Evaluation                                              99

Apr`s avoir d´bloqu´ les instructions associ´es dans W a un signal qui a ´t´ ´mis, l’ex´cution
    e         e      e                      e          `                 eee           e
                               e
de l’instant continue avec la r´action .
   La seconde ´tape de l’ex´cution d’un instant applique la r´action −→ a tous les ´l´ments
              e            e                                 e          `          ee
de W :
                                        S, G, ∅     eoi   S, G , ∅    ∅

        G(a, i) = t      S, G, ∅     ta −→ S, G , W
                                      i                     C        S, G , W      eoi   S, G , W   C
                          S, G, (W + [(a, i)/n])      eoi   S, G , W , W          C ,C

    e                                                                               e
L’op´ration + ajoute la continuation k dans la file d’attente du signal n. Elle est d´finie par :
                      W(n )      si n = n
(W + [k/n])(n ) =
                      k, W(n) si n = n
                 ` e          e
   Il nous reste a d´finir la r´action d’une instruction t :

                                    S, G, W       ta −→ S , G , W
                                                   i                      C

6.3.2      e
         Ex´cution d’une instruction
    La r`gle S, G, W ta −→ S , G , W
        e                i                    C d´finit la r´action de l’instruction t d´finie dans
                                                 e         e                           e
le groupe a a la position i. Cette r´action se fait dans un environnement de signaux S. W est
             `                      e
                                            e
l’ensemble des instructions en attente. La r´action de t peut modifier l’ensemble des instructions
en attente et g´n´rer un ensemble C d’instructions a ex´cuter dans l’instant.
               e e                                   ` e
                  c          e         e
    Nous commen¸ons par d´finir l’ex´cution d’une expression instantan´e e. e

                                              e/S ⇓ v/S
                                S, G, W    ea −→ S , G, W
                                            i                        (a, i + 1)

      e     e                        e                                                          e
e est ´valu´ en la valeur v et l’ex´cution dans l’instant de l’instruction (a, i + 1) est demand´e.
  e
e ´tant l’instruction (a, i), l’instruction (a, i + 1) est sa continuation.
    Le pr´dicat e/S ⇓ v/S d´finit l’´valuation d’une expression e en une valeur v dans un envi-
          e                      e      e
                                                                          ee   e            e
ronnement de signaux S. L’environnement S contient les signaux cr´´s et ´mis par la r´action.
      e       e               e             e
Les r`gles d´finissant ce pr´dicat sont d´finies figure 6.1. Ce sont celles de ML auxquelles nous
                e
ajoutons les op´rations sur les signaux.
    Nous regardons maintenant l’attente d’un signal. On illustre ainsi l’utilisation des files d’at-
tente W.
                                                  n∈S
                      S, G, W      (await immediate n)a −→ S, G, W
                                                      i                           (a, i + 1)
                                     n∈S          W = W + [(a, i)/n]
                         S, G, W      (await immediate n)a −→ S, G, W
                                                         i                               ∅
             e     e                    e           e                      e
Dans la premi`re r`gle, le signal est pr´sent. On ex´cute donc instantan´ment la continuation.
                               e                                                    e
Dans la seconde, le signal test´ est absent, on enregistre alors l’expression associ´e au signal n
dans W.

                                                    n∈S
                      S, G, W   (present n then k1 else k2 )a −→ S, G, W
                                                            i                                k1
100                                                 6. Glouton




                       e[x ← rec x = e]/S ⇓ v/S                  e1 /S ⇓ v/S1     e2 [x ← v]/S1 ⇓ v /S
      v/S ⇓ v/S
                           rec x = e/S ⇓ v/S                          let x = e1 in e2 /S ⇓ v /S

   e1 /S ⇓ λx.e/S1     e2 /S1 ⇓ v/S2       e[x ← v]/S2 ⇓ v /S              e1 /S ⇓ v1 /S1        e2 /S1 ⇓ v2 /S
                        e1 e2 /S ⇓ v /S                                         (e1 , e2 )/S ⇓ (v1 , v2 )/S

  e/S ⇓ n/S    (b, v) = S p (n)      e/S ⇓ n/S         (b, v) = S p (n)      e1 /S ⇓ n/S1         e2 /S1 ⇓ v/S
        pre e/S ⇓ b/S                         pre ?e/S ⇓ v/S                emit e1 e2 /S ⇓ ()/S + [v/n]

      e1 /S ⇓ v1 /S1   e2 /S1 ⇓ v1 /S2        n ∈ Dom(S2 ) e/S2 [(v1 , v2 , (false, v1 ), ∅)/n] ⇓ v/S
                          signal x default e1 gather e2 in e/S ⇓ v/S



                                    e                                e
                        Fig. 6.1 – R´action des expressions instantan´es.


                            n∈S            eoi ∈ S         W = W + [(a, i)/n]
                  S, G, W      (present n then k1 else k2 )a −→ S, G, W
                                                           i                                ∅
                                              n∈S          eoi ∈ S
                  S, G, W     (present n then k1 else k2 )a −→ S, G, W
                                                          i                                 k2
                                                      e           e              e
Pour la construction present, lorsque le signal est pr´sent, on ex´cute instantan´ment la branche
                                        `                             ` e
then. On ajoute donc l’instruction k1 a l’ensemble des instructions a ex´cuter. Quand le signal
                                                                                       eee
est absent, il faut distinguer deux cas. Si le signal de fin d’instant n’a pas encore ´t´ ´mis, il
                          e
peut encore y avoir des ´missions de signaux. Dans ce cas, il faut donc attendre pour savoir si n
   e    e                                            e                                          e
va ˆtre ´mis pendant l’instant ou pas. Si eoi est pr´sent, cela signifie que l’instant est termin´,
               e         e                                                           e
et que l’on pr´pare la r´action pour l’instant suivant. On peut donc demander l’ex´cution de la
branche else.
                                         e
    Afin de coder la composition parall`le, nous avons l’instruction split :


                         S, G, W         (split k1 k2 )a −→ S, G, W
                                                       i                     (k1 , k2 )
                                           e
Cette instruction demande simplement l’ex´cution des instructions k1 et k2 dans l’instant.
                                           e           e                   e
    Pour la terminaison des branches parall`les et le d´clenchement de la s´quence, nous voyons
l’instruction term :
                     G(a) = {I     cpt   k}      cpt > 1         G = G[{I       cpt−1   k}/a]
                                  S, G, W        terma −→ S, G , W
                                                     i                      ∅

                                               G(a) = {I     1   k}
                                  S, G, W       terma −→ S, G\a, W
                                                    i                       k
                                                   ´
                                              6.3. Evaluation                                        101

        e e                                        e
term d´cr´mente le compteur de branches parall`les de son groupe. Lorsque toutes les branches
      e                           e          e                                  e      e
parall`les d’un groupe ont termin´ leur ex´cution, la continuation k est alors d´clench´e. Dans
ce cas, le groupe a ´tant termin´, il est retir´ de l’environnement G.
                    e           e              e
    L’instruction run e ajoute de nouveaux groupes a l’environnement G et les ex´cute.
                                                        `                          e

                    e/S ⇓ process(λx.G , k)/S              G = G.(G [x ← (a, i + 1)])
                                 S, G, W       (run e)a −→ S , G , W
                                                      i                    k

L’expression e s’´value en une d´finition de processus. Dans la d´finition process(λx.G , k), G
                  e                 e                               e
est param´tr´ par la continuation x. Donc pour ajouter G a G, on substitue x par la continuation
           e e                                              `
du run. L’op´ration G.G ´tend la d´finition de G avec celle de G . Elle est possible uniquement
              e              e          e
s’il n’y a pas de collisions entre les noms de groupes (Dom(G) ∩ Dom(G ) = ∅). Afin de garantir
             ee        e                e
cette propri´t´, les r`gles sont donn´es modulo le renommage des groupes.
               e
     Pour les d´clarations de signaux et de variables locales, on a une approche similaire.

         e1 /S ⇓ v1 /S1     e2 /S1 ⇓ v2 /S2    n ∈ Dom(S2 ) S = S2 [(v1 , v2 , (false, v1 ), ∅)/n]
                                              G = G.(G [x ← n])
          S, G, W     (signal x default e1 gather e2 in (G , k))a −→ S , G , W
                                                                i                             k

           e                        e                      e
Pour la d´claration de signal, on ´value la valeur par d´faut (v1 ) et la fonction de combinaison
            `
(v2 ). Puis a partir de ces informations, on enrichit l’environnement de signaux avec un nouveau
signal n pour construire l’environnement S . Enfin on substitue x par n dans la d´finition de G .
                                                                                    e

                                    e/S ⇓ v/S         G = G.(G [x ← v])
                          S, G, W    (let x = e in (G , k))a −→ S , G , W
                                                           i                      k
                     e
Pour le let/in, on ´value simplement e en v et on substitue x par v dans les groupes qui
 e
d´finissent le corps du let.
                                    e
   Nous terminons avec le await valu´.
                              (n ∈ S) ∨ (eoi ∈ S)         W = W + [(a, i)/n]
                      S, G, W        (await n(x) in (G , k))a −→ S, G, W
                                                            i                      ∅


        n∈S      eoi ∈ S        S(n) = (d, g, p, m)        v = fold g m d       G = G.(G [x ← v])
                      S, G, W        (await n(x) in (G , k))a −→ S, G, W
                                                            i                      k

                                                         `
Tant que le signal n est absent ou que l’on n’est pas a la fin d’instant, il faut attendre. Une
                          e                                          e
fois ces deux conditions r´unies, on peut calculer la valeur v associ´e au signal (comme dans la
s´mantique comportementale page 55) et substituer x par v dans la d´finition de G .
 e                                                                       e

6.3.3     e              e                  e
         S´mantique sans ´chappement de port´e
    En Junior, la liaison des noms est dynamique alors qu’elle est statique en ReactiveML.
                                   e     e     e                   e
Donc en Junior, il n’y a pas de ph´nom`ne d’´chappement de port´e. On peut ainsi implanter
                            e           e                 o                          e
la boucle loop comme un op´rateur de r´initialisation plutˆt que comme une fonction r´cursive.
                                           e                        e
Cette approche limite les allocations et d´sallocations pendant l’ex´cution et conduit donc a`
une implantation plus efficace.
102                                                  6. Glouton

    Dans le programme suivant, le signal channel transporte des noms de signaux. Il est ´mise
                       e               e    e`       e                         e
avec pour valeur associ´e le signal s d´clar´ a l’int´rieur du loop. La valeur ´mise sur channel
     e   ee      e     `      e
est r´cup´r´e et ´mise a l’ext´rieur de la boucle.
  signal channel in
  signal s in
  loop
     signal s in
     emit channel s;
     pause
  end
  ||
  await one channel (x) in
  emit x
  ||
  await s;
  print_string "Present"
          e                                                                      e
Avec la s´mantique de ReactiveML, le message Present n’est jamais affich´. Mais avec la
 e                                   e                     e
s´mantique de Junior, le signal s ´mis sur channel est li´ dynamiquement au signal s le plus
                                                  e    e
externe. Dans ce cas, l’instruction await s peut ˆtre r´duite et le message Present est affich´.e
                         e                    e
Comme il n’y a pas d’´chappement de port´e, il n’y a jamais plus d’une instance active du
          e     `      e
signal s d´finie a l’int´rieur de la boucle.
                     e        e                    e                e
    Dans un interpr`te sans ´chappement de port´e, il n’est pas n´cessaire d’allouer un signal
      `                                      e                                        e
frais a chaque fois que l’on rencontre une mˆme instruction signal, nous pouvons r´utiliser la
  e             e                                                      e
mˆme cellule m´moire dans l’environnement S. Pour implanter la r´initialisation, il faut que
                                                                      e
les groupes gardent la valeur initiale du compteur de branches parall`les actives. Nous ajoutons
donc en indice du symbole cette valeur.
                                                         cpt
                                           G ::= {I      cptinit   k}

                                                e                  e         e
Ainsi maintenant lorsqu’un groupe termine son ex´cution, au lieu d’ˆtre retir´ de l’environne-
                          e         e
ment des groupes, il est r´initialis´ :
                                          1                             cpt
                            G(a) = {I     cpt   k}      G = G[a ← {I    cpt   k}]
                                  S, G, W       terma −→ S, G , W
                                                    i                   k
                       e                                                       e
   Enfin, nous pouvons d´finir le loop comme un groupe qui prend son point d’entr´e comme
continuation.
 T r(loop P, a, i) =
    let b = f resh() in
    let (G, I, k, cpt, i ) = T r(P, b, 1) in
    let G = {I cpt k} in
                    cpt
    ([G/b], ∅, k, 1, i)
                     e
     Pour donner la s´mantique de Junior, il faut apporter d’autres modifications afin de coder
                                                     e       e
la liaison dynamique. Mais cette approche peut aussi ˆtre int´ressante en ReactiveML. Si on
        `                                         e                    e
arrive a identifier des parties de programmes sans ´chappement de port´e, on peut appliquer la
  e
mˆme technique d’implantation.
                                                              o
                         6.4. Ajout des constructions de contrˆle                           103

6.4                                     o
        Ajout des constructions de contrˆle
        e                                                e
   La s´mantique de Glouton que nous venons de pr´senter ne prend pas en compte les
                                   e
constructions de suspension et pr´emption. L’ajout de ces constructions apporte une grande
          e`     e                     e                               e
complexit´ a la r´alisation des interpr`tes. De nombreux choix peuvent ˆtre faits pour les im-
                                       e                       e e
planter. La pertinence de ces choix d´pend du programme ex´cut´. Nous proposons ici une
      e
premi`re solution pour les deux constructions. Nous en verrons une autre chapitre 7.3.


6.4.1   La suspension
    Nous traitons ici la construction do/when. Nous allons voir comment remplacer cette construc-
tion par des await.
                                    e                           e                          e
    La construction do/when peut ˆtre vue comme le test de pr´sence d’un signal avant l’ex´cution
                                                                                     e
de chaque instruction de son corps. Par exemple, les deux programmes suivants sont ´quivalents :
    do                                         await immediate s;
       emit a;                                 emit a;
       pause;                                  await immediate s;
       emit b                                  pause;
    when s                                     await immediate s;
                                               emit b
                                                                               e
    Nous pouvons affiner l’analyse en remarquant qu’il suffit de tester la pr´sence du signal qui
      o        e                             e                                           e
contrˆle l’ex´cution qu’une seule fois au d´but de chaque instant. Il n’est donc pas n´cessaire
                             e
de conserver les await apr`s les expressions instantan´es.e
    do                                         await immediate s;
       emit a;                                 emit a;
       pause;                                  pause;
       emit b                                  await immediate s;
    when s                                     emit b
                                        e      e e
    Pour les instructions qui peuvent ˆtre ex´cut´es sur plusieurs instants comme await, Il faut
                                                 o `
faire attention de bien tester le signal de contrˆle a chaque instant et pas seulement au premier
                                                                     e
instant. Par exemple, les deux programmes suivants ne sont pas ´quivalents :
    do                                         await immediate s;
       await immediate a;                      await immediate a;
       emit b                                  await immediate s;
    when s                                     emit b
           e                              e                       e              e
Si s est ´mis au premier et au troisi`me instants et a est ´mis au deuxi`me instant, alors
                           e                                      e
le programme de droite ´met b alors que celui de gauche ne l’´met pas.
            e                e                                      e e
    Pour r´soudre ce probl`me, nous utilisons les configurations ´v´nementielles. Les configura-
                                                     e                e
tions permettent d’exprimer des expressions bool´ennes sur la pr´sence des signaux. En parti-
culier, la pr´sence simultan´e de deux signaux peut ˆtre test´e avec l’op´rateur ∧. Les configu-
              e               e                         e       e          e
         e e
rations ´v´nementielles existent en Junior et nous verrons chapitre 11.3 comment elles ont ´t´ee
   e e
int´gr´es dans ReactiveML.
                                                  e e
    En utilisant les configurations, l’exemple pr´c´dent devient :
    do                                         await immediate (s /\ a);
       await immediate a;                      emit b
       emit b
    when s
104                                           6. Glouton

                                      e               e
Ici, il faut bien que s et a soient pr´sents dans le mˆme instant pour pouvoir passer le await et
e
´mettre b.
                e
     Donc la m´thode que nous utilisons pour traiter le do/when est de le traduire avec des await
                        e e
et des configurations ´v´nementielles. La fonction de transformation de programme a la forme
suivante :
                                                   c
                                               e       e

                   `                                          o       e
e est l’expression a traduire, c est la configuration qui contrˆle l’ex´cution de e, et e est le
                      e
programme transform´. Cette transformation est faite directement sur le source ReactiveML.
Ainsi, nous pouvons utiliser cette transformation pour toutes les implantations du langage.
                            e
    Les configurations utilis´es dans la transformation sont seulement des conjonctions. Elles
      e
sont d´finies par :
                                   c ::= n | x | true | c ∧ c

n est un nom de signal, x est une variable, true est la configuration qui est toujours vraie et
c ∧ c la conjonction de deux configurations. La valeur true est utilis´e pour transformer les
                                                                            e
programmes qui ne sont pas dans un do/when.
                                           e
    La fonction de transformation est d´finie figure 6.2. Commentons ces r`gles : e
                                     e
    – Pour la transformation des d´finitions de processus (process e), nous introduisons un nom
                   `       e
      x qui sert a param´trer la transformation du corps du processus car nous ne connaissons
                                                           e e
      pas le contexte dans lequel le processus sera ex´cut´.
                                        o                                       e
    – run donne le contexte de contrˆle courant au processus qu’il doit ex´cuter.
                                                                    e
    – Pour les lieurs comme signal/in et let/in, il faut v´rifier que le nom qui est introduit
                                                    e
      ne capture pas une variable qui est utilis´e dans la configuration. En cas de capture, nous
      pouvons toujours appliquer une α-conversion.
                            e      e
    – Un await est ajout´ derri`re la pause car l’instruction qui la suit sera toujours ex´cut´ee e
      `                e                  e                               e                    e
      a l’instant d’apr`s. Il faut donc v´rifier si la configuration est pr´sente avant de l’ex´cuter.
                                                `                        e                   e
    – Dans la construction present, le test a l’absence ajoute un d´lai. Il faut donc v´rifier si
                                                   e                                          e
      la configuration est satisfaite avant d’ex´cuter la branche else. Au contraire, l’ex´cution
                             e                e                     e         e     e e
      de la branche then ´tant instantan´e, si le test de pr´sence a pu ˆtre ex´cut´, c’est que
                               e                            e
      la configuration est pr´sente. Il n’est donc pas n´cessaire de la tester de nouveau dans la
      branche then.
    – Comme nous l’avons vu, await/immediate doit tester la conjonction de la configuration
                o                               e                            e               e
      de contrˆle et du signal attendu. L’ex´cution de sa continuation ´tant instantan´e, nous
                     `                                e
      n’avons pas a retester la configuration apr`s le await.
                                                        c
    – Pour la construction await/in, nous commen¸ons par attendre la conjonction de la confi-
                         o                                     e
      guration de contrˆle et du signal. Un fois le signal ´mis et la configuration satisfaite, on
         e                                   e    e              e
      ex´cute le corps (body). Le corps r´cup`re instantan´ment la valeur du signal car avec le
                 e e                     u                         e
      await pr´c´dent nous sommes sˆr que le signal est pr´sent. La partie droite du await/in
      e        e e `                   e                                                       e
      ´tant ex´cut´e a l’instant d’apr`s, il faut tester la configuration avant de pouvoir l’ex´cuter.
                                                                  o
    – Enfin, pour le do/when, le nouveau contexte de contrˆle c est la conjonction du contexte
      courant et de x. On transforme le corps du do/when dans ce contexte. L’expression rendue
                                                               e
      par la transformation est le corps du do/when gard´ par l’attente de c .
                          e
    – Toutes les autres r`gles propagent seulement la transformation.
              e            e
    Afin de d´finir compl`tement le traitement de la suspension, il nous faut maintenant d´finir    e
                                                             e                       e
le await/immediate qui attend plusieurs signaux. Les r`gles sont quasiment les mˆmes que dans
la section 6.3. Il suffit de remplacer les tests n ∈ S et n ∈ S par des tests de configurations.
                                                                          o
                                     6.4. Ajout des constructions de contrˆle                                                                                             105




                                                                                            c                                                                c
            c                                 c
                                                                                    e           e                          x ∈ f v(c)                   e        e
      x         x           const                  const
                                                                                            c                                               c
                                                                        λx.e                    λx.e                      rec x = e             rec x = e

            c                    c                                  c                                   c                               c                        c
      e1         e1        e2            e2                   e1            e1                  e2           e2                 e1          e1          e2           e2
                      c                                                                 c                                                           c
           e1 e2           e1 e 2                        emit e1 e2                             emit e1 e2                          e1 ;e2                  e1 ;e2

       c                    c                                                                            x                                              c
 e1         e1        e2         e2                           x ∈ f v(e)                         e               e                              e            e
                 c                                                              c                                                                c
  e1 ||e2             e1 ||e2                           process e                       λx.process e                                run e               run (e c)

                                                                            c                                c                  c
                                     x ∈ f v(c)                 e1              e1                  e2               e2     e       e
                                                                                        c
signal x default e1 gather e2 in e                                                              signal x default e1 gather e2 in e

                                         c                      c
 x ∈ f v(c)                     e1            e1         e2         e2
                                     c                                                                                c
let x = e1 in e2                             let x = e1 in e2                                    pause                    pause;await immediate c

                                                                    c                                   c
                                                              e1            e1                  e2           e2
                                                          c
present x then e1 else e2                                      present x then e1 else (await immediate c;e2 )

                                                                                c
                                await immediate x                                       await immediate (c ∧ x)

                                              c
           y ∈ f v(c)                e1            e1    body = await x(y) in await immediate c;e1
                                                                    c
                           await x(y) in e1                                 await immediate (c ∧ x);body

                                                                                                         c
                                                              c =c∧x                                e            e
                                                                        c
                                             do e when x                        await immediate c ;e


                                              Fig. 6.2 – Suppression des do/when
106                                             6. Glouton

Ainsi, nous devons d´finir c ∈ S et c ∈ S.
                    e

                                      c∈S      ssi        ∀n ∈ c. n ∈ S
                                      c∈S      ssi        ∃n ∈ c. n ∈ S

                                  e                                                 e
Donc une configuration est dite pr´sente si tous les signaux qui la composent sont pr´sents. Elle
est absente si au moins un des signaux est absent.

6.4.2           e
           La pr´emption
                                                                         e
    Contrairement au do/when, la construction do/until n’est pas trait´e par transformation
                                     e
dans des instructions du noyau. Nous ´tendons et modifions le langage des groupes afin de traiter
     e                           e       e                          e
la pr´emption. Nous devons donc ´tendre ´galement le langage interm´diaire avec continuation :

                           p ::=       . . . | do P until x(y) -> P done.p

        e
    L’id´e pour le traitement du do/until est de traduire le corps dans un groupe et d’avoir une
                                  e                     e
instruction kill qui attende la pr´sence du signal de pr´emption pour supprimer le corps. Nous
                                                        e                              e
ajoutons donc aux instructions le kill qui attend la pr´sence de x pour effectuer la pr´emption
    e             e                       e               u
et d´clencher l’ex´cution du traitement d’´chappement o` y prend la valeur du signal :

                                 t ::=       . . . | kill x(y) -> (G, k)

                          e      e                e
    Pour comprendre la n´cessit´ de modifier la d´finition des groupes, il faut remarquer que
                               e
la traduction que nous avons d´finie section 6.2.2 fait perdre la structure du programme. Tous
les groupes sont d´finis au mˆme niveau dans G, on a donc perdu la notion de sous-expression.
                   e         e
Illustrons cela sur un exemple :
do
  (emit x || emit y);
  emit z
until s done
                                                                                  e
La traduction du corps du do/until dans un groupe a avec la continuation k cr´e un groupe b
                                     e                                   e
dans lequel la partie gauche de la s´quence est traduite. Le point d’entr´e de ce programme est
l’instruction (b, 1) et l’environnement de groupes G est le suivant :

                 {split (b, 2) (b, 4)1 , (emit x)2 , term3 , (emit y)4 , term5      2   (a, 1)}/b;
          G=
                 {(emit z)1 , term2 1 k}/a

                           ıt
On constate qu’il n’apparaˆ pas dans le groupe a que b est un sous groupe de a. Ceci pose
     e                                      e
probl`me pour le do/until car en cas de pr´emption il faut supprimer a et b.
    La solution que nous proposons est d’ajouter dans chaque groupe l’ensemble de ses fils.
Ceci permet de reconstituer l’arbre des groupes qui correspond la structure du programme. Sur
            e e
l’exemple pr´c´dent cela nous donne l’environnement :

                {∅ | split (b, 2) (b, 4)1 , (emit x)2 , term3 , (emit y)4 , term5       2   (a, 1)}/b;
         G=
                {b | (emit z)1 , term2 1 k}/a

                   e
      La nouvelle d´finition des groupes est la suivante :
                                              cpt
                              G ::= {F | I           k}         F ::= ∅ | id, F
                                                                    o
                               6.4. Ajout des constructions de contrˆle                     107

                             e     e
    Comme nous avons modifi´ la d´finition des groupes, il faut modifier la fonction de traduc-
tion. Nous ajoutons l’ensemble F des noms de groupes directement cr´´s par la traduction a sa
                                                                     ee                  `
valeur de retour.
                               T r(P, id, i) = (F, G, I, k, cpt, i )
                 `           `
Les modifications a apporter a la fonction de traduction sont assez simples. Illustrons ces chan-
                                   e              e
gements sur un des cas les plus int´ressants, la s´quence :
 T r(P1 ;P2 , a, i) =
    let (F2 , G2 , I2 , k2 , cpt2 , i2 ) = T r(P2 , a, i) in
    let b = f resh() in
    let (F1 , G1 , I1 , k1 , cpt1 , i1 ) = T r(P1 , b, 1) in
    let G1 = {F1 | I1 cpt1 k2 } in
    (F2 , [G1 /b] ∪ G1 ∪ G2 , I2 , k1 , cpt2 , i2 )
La traduction de P1 se faisant dans b, on ajoute F1 dans la d´finition de G1 . La traduction de
                                                               e
P2 se faisant quant a elle directement dans a, F2 est l’ensemble des noms de groupes rendu par
                    `
la traduction.
                                                                                  e     e
    Maintenant que nous avons introduit l’instruction kill et que nous avons modifi´ la d´finition
                                   `     e
des groupes, nous pouvons passer a la d´finition de la traduction du do/until.
 T r(do P1 until x(y) -> P2 done.p, a, i) =
    let (G, I, k, cpt, i ) = T r(p, a, i + 1) in
    let c = f resh() in
    let (F2 , G2 , I2 , k2 , cpt2 , i2 ) = T r(P2 , c, 1) in
    let G2 = {F2 | I2 cpt2 k} in
    let b = f resh() in
    let (F1 , G1 , I1 , k1 , cpt1 , i1 ) = T r(P1 , b, 2) in
    let G1 = {F1 | (kill x(y) -> ([G2 /c] ∪ G2 , k2 ))1 , I1 cpt1 k} in
    ((b, c, F), [G1 /b] ∪ G1 ∪ G, ((split (b, 1) k1 )i , I), (a, i), cpt, i )
La traduction commence par la traduction de la continuation p. Puis P2 et P1 sont traduits
                                                                e
respectivement dans les nouveaux groupes c et b avec la mˆme continuation k. L’instruction
                e
kill est ajout´e au groupe b. Enfin on ajoute une instruction split au groupe a qui va servir
                 e                                    `             e
de point d’entr´e. Cette instruction split permet a la fois d’ex´cuter P 1 et l’instruction kill
          o       e
qui contrˆle l’ex´cution du programme. Cette instruction attend la fin d’instant et que le signal
     e                         e                                                   e
soit ´mis pour effectuer la pr´emption. Si le corps du do/until termine son ex´cution avant
              e                                         e
qu’il y ait pr´emption, l’instruction kill est supprim´e.
                       ` e            e         e
    Il nous reste enfin a d´crire les r`gles de r´action de l’instruction kill.
                                       eoi ∈ S         W = W + [(a, i)/n]
                           S, G, W       (kill n(x) -> (G , k))a −→ S, G, W
                                                               i                ∅
        e    e                                                      e
La premi`re r`gle attend la fin d’instant avant de tester s’il y a pr´emption ou pas.

                                                    a ∈ Dom(G)
                           S, G, W       (kill n(x) -> (G , k))a −→ S, G, W
                                                               i                ∅
La condition a ∈ Dom(G) teste si le groupe a existe toujours ou pas dans l’environnement G.
                                                                             e    e
S’il n’est plus dans l’environnement, cela signifie que le do/until a termin´ l’ex´cution de son
                                                e                                            e
corps. Dans ce cas il ne peut plus y avoir de pr´emption, l’instruction kill est donc supprim´e.
108                                             6. Glouton


                    eoi ∈ S       a ∈ Dom(G)       n∈S       W = W + [(a, i)/n]
                        S, G, W     (kill n(x) -> (G , k))a −→ S, G, W
                                                          i                ∅
`                                                          e                e
A la fin d’instant, si le corps du do/until n’est pas termin´, on teste la pr´sence du signal. S’il
est absent, l’instruction kill est mise en attente.
                               a                 u         e                e
    Il ne nous reste plus qu’` traiter le cas o` il y a pr´emption. L’id´e de ce dernier cas
est de supprimer le groupe du corps du do/until et ses sous-groupes ainsi que toutes les
instructions appartenant a ces groupes pr´sentes dans W et C. Nous d´finissons la fonction
                            `               e                              e
remove(a, G, W, C) qui supprime tout ce qui concerne a et ses sous-groupes de G, W et C.

 remove(a, G, W, C) =
   Set G := G, W := W, C := C in
   forAll b sous-groupe de a do
      G , W , C := remove(b, G , W , C )
   done ;
   (G \a, W \a, C \a)

Nous constatons qu’il faut avoir acc`s a l’ensemble C des instructions a ex´cuter a l’instant
                                      e `                                   ` e        `
                e          e                       e         e
courant pour r´aliser la pr´emption. Or, dans les r`gles de r´actions, cette information n’est pas
pr´sente. Il faut donc ajouter C dans la d´finition des r´actions :
  e                                       e              e

                                  S, G, W, C    ta −→ S , G , W
                                                 i                    C

                                      e         e                e e                       e
Cette modification dans la forme des r`gles de r´action modifie l´g`rement l’ensemble des r`gles
pr´c´dentes. En effet, elles doivent conserver toutes les instructions qui sont dans C en plus de
  e e
                 e e           e
celles qu’elles g´n`rent. Les r`gles

                                   S, G, W     ta −→ S , G , W
                                                i                 C

deviennent
                              S, G, W, C       ta −→ S , G , W
                                                i                 C ∪C
                      e                            e
      Finalement, la r`gle du kill qui traite la pr´emption est la suivante :

              eoi ∈ S    a ∈ Dom(G)          n∈S       G , W , C = remove(a, G, W, C)
                  S(n) = (d, g, p, m)      v = fold g m d    G = G .(G [x ← v])
                    S, G, W, C     (kill n(x) -> (G , k))a −→ S, G , W
                                                         i                  k, C

               e              e             e             e
Dans la premi`re ligne des pr´misses, on v´rifie que la pr´emption peut avoir lieu et on calcule
          e                                            e
le nouvel ´tat du programme dans lequel on a supprim´ le corps du do/until. La seconde ligne
 e    e                           e         e                       e
r´cup`re la valeur du signal et pr´pare l’ex´cution du traitement d’´chappement.


6.5       Conclusion
                 e              e    e                                            e e
    Nous avons d´fini une premi`re s´mantique pour l’implantation efficace du mod`le r´actif.
Dans cette s´mantique, les programmes sont d´compos´s en un ensemble C d’instructions a
             e                                 e       e                                   `
ex´cuter, des files d’attente W et des groupes G qui gardent la structure du programme. L’or-
  e
                                       e                                            e
donnancement des programmes est d´fini par l’ordre d’activation des instructions pr´sentes
                                      6.5. Conclusion                                        109

dans C. La composition parall`le ´tant associative et commutative en ReactiveML, il n’y a
                                e e
donc aucune contrainte sur le choix des instructions dans C.
    Nous pouvons constater que dans l’activation de fin d’instant toutes les instructions en
                    e
attentes sont activ´es. Or nous savons que les instructions await/immediate ne peuvent pas
e                                                 e                                   e
´voluer alors que les instructions present sont r´duites. Dans l’implantation de la s´mantique,
                                                                          e
nous faisons la distinction entre ces deux types d’attente. Ainsi, nous s´parons l’environnement
de files d’attente W en deux environnements Wa et Wp qui conservent respectivement les ins-
                                                          `
tructions await/immediate et present. Comme cela, a la fin de l’instant, nous savons que
nous pouvons conserver tel quel l’environnement Wa alors qu’il faut faire r´agir l’environne-
                                                                               e
ment Wp . Enfin pour l’instruction await/in, tant que le signal test´ est absent, l’instruction
                                                                        e
est enregistr´e dans Wa et lorsque le signal est ´mis, l’instruction attend la fin d’instant dans
              e                                   e
l’environnement Wp . Dans cette s´mantique, nous avons donc de l’attente passive intra-instants
                                    e
et inter-instants.
            e          e          e         `                  e
    Cette s´mantique ´tant une s´mantique a petits pas, elle s’´tend simplement avec la construc-
                         ee             e
tion await/one et les r´f´rences. Les r`gles pour le await/one sont les suivantes :

                             n∈S       G = G.(G [x ← one(S v (n))])
                   S, G, W    (await one n(x) in (G , k))a −→ S, G, W
                                                         i                  k

                                 n∈S       W = W + [(a, i)/n]
                   S, G, W    (await one n(x) in (G , k))a −→ S, G, W
                                                         i                  ∅
          ee                                                                      e
Pour les r´f´rences, il faut ajouter un environnement M qui permet de conserver l’´tat de la
 e                 e            e                        ee
m´moire et il faut ´tendre la s´mantique de ML avec les r´f´rences.


 e   e
R´sum´
                                        e                  e                     e   e
    Les trois points principaux pour r´aliser un interpr`te efficace du mod`le r´actif sont :
                                             e
(1) l’attente passive des signaux, (2) la r´duction du temps de parcours de la structure du
                                               e
programme et (3) avoir la composition parall`le associative et commutative. L’attente passive
                                                               e
est certainement le point le plus important. Elle permet d’ex´cuter les instructions uniquement
                              e            e                e                   e
lorsque le signal dont elles d´pendent est ´mis. Ainsi cela ´vite de tester syst´matiquement des
                                 e
instructions qui ne peuvent pas ´voluer.
         e                        e                       e e                    e       e
    La s´mantique Glouton int`gre les trois points pr´c´dents. Elle est bas´e sur l’id´e qu’il
faut toujours “aller de l’avant” en gardant les tests de signaux qui sont absents dans des files
                e                          e
d’attente. La s´mantique n’est pas donn´e directement sur le langage source ReactiveML,
                                          e                           e
mais sur un format que nous avons appel´ les groupes. Dans cette s´mantique, les programmes
sont d´compos´s en un ensemble C d’instructions a ex´cuter, des files d’attente W et des groupes
       e       e                                  ` e
G qui gardent la structure du programme. L’ex´cution d’un instant consiste a ex´cuter toutes
                                                 e                               ` e
les instructions de C.
                                     Chapitre 7

           e
      Une s´mantique efficace pour le
              e    e
           mod`le r´actif II : Lk

        e                      e
    La s´mantique que nous pr´sentons ici est beaucoup plus proche de l’implantation actuelle
                          e                         e e
de ReactiveML que la s´mantique du chapitre pr´c´dent. Elle se base sur l’utilisation de files
d’attente et de continuations mais nous n’utilisons plus les groupes. Cette fois ci, nous donnons
    e                e
la s´mantique compl`te du langage avec le let/and/in.
                                        e                            e e
    La structure de ce chapitre est la mˆme que celle du chapitre pr´c´dent. Nous commen¸ons c
      e           e                                                                        e
par pr´senter la s´mantique d’un sous-ensemble du langage dans lequel il n’y a pas d’op´ration
                       e
de suspension ni de pr´emption. Puis, nous ajoutons ces deux constructions.


7.1    Le langage avec continuation Lk
                                  e             e
   Le langage Lk sur lequel nous d´finissons la s´mantique a la syntaxe abstraite suivante :

             k ::=      end | κ | e.k | present e then k else k
                      | await immediate e.k | await e(x) in k | run e.k
                      | split (λx.(k, k)) | join x i.k | def x and y in k
                      | signal x default e gather e in k

             e ::=      x | c | (e, e) | λx.e | e e | rec x = e | pre e | pre ?e | emit e e
                      | signal x default e gather e in e | process Λκ.k

                                                         e
    Dans ce langage, κ est une variable qui sera substitu´e par une continuation (k) et i peut
prendre la valeur 1 ou 2. L’expression end marque la fin du programme. Il ne faut pas la
                                                 e e
confondre avec l’instruction term du chapitre pr´c´dent qui indique la fin d’une branche pa-
    e                                       e
rall`le. Comme une expression se termine n´cessairement par un end, la continuation de l’ex-
                            e
pression present est propag´e dans ses deux branches. En effet, si on avait l’expression

                                (present e then k1 else k2 ).k3

                                        e      e e
la continuation k3 ne pourrait jamais ˆtre ex´cut´e car k1 et k2 se terminent avec un end qui
                                                                           `
marque la fin du programme. Les expressions split, join et def servent a coder le let/and/in.
                          e                  e
Le split commence l’ex´cution du parall`le, le join synchronise la terminaison et le def
 e    e                        e
r´cup`re les valeurs avant d’ex´cuter la continuation. La variable x, introduite dans le split et

                                                 111
112                                                    7. Lk




         Ck [e] = C[e].k   si 0     e      Ck [run e] = run C[e].k           Ck [e1 ;e2 ] = C(Ck [e2 ]) [e1 ]

         Ck [present e then e1 else e2 ] = present C[e] then Ck [e1 ] else Ck [e2 ]

         Ck [await immediate e] = await immediate C[e].k

         Ck [await e1 (x) in e2 ] = await C[e1 ](x) in Ck [e2 ]          avec    x ∈ f v(k)

         Ck [signal x default e1 gather e2 in e] =
              signal x default C[e1 ] gather C[e2 ] in Ck [e]             avec     x ∈ f v(k)

         Ck [let x = e1 and y = e2 in e] = split (λz.(C(join z 1.k ) [e1 ], C(join          z 2.k ) [e2 ]))
         avec k = def x and y in Ck [e] et z ∈ f v(e1 ) ∪ f v(e2 ) ∪ f v(k)



                           Fig. 7.1 – Traduction de ReactiveML vers Lk .

      e                                        e                               e             `
utilis´e dans le join, est une variable partag´e par les deux branches parall`les. Elle sert a la
                                 e                e
synchronisation. Enfin, le param`tre i du join diff´rencie la branche gauche de la branche droite
          e                                  e                             e
du parall`le. Pour les expressions instantan´es (e), il faut noter que la d´finition de processus
           e e
est param´tr´e par sa continuation.
                           e                      e                              e
    Le langage Lk est diff´rent du format interm´diaire que nous avons utilis´ pour la trans-
                                                                         e    e
formation vers les groupes dans la section 6.2.2. Comme nous devons r´cup´rer les valeurs des
                e `                    e                                           e
branches parall`les a la fin de leur ex´cution, nous ne pouvons pas attendre la s´quence pour
                                               `                            e
faire la synchronisation de la terminaison. A la place du couple term/s´quence, nous avons
l’instruction join avec sa continuation.

Traduction
    La fonction Ck [e] traduit l’expression ReactiveML e dans Lk avec une transformation
                                                          e                          e e
CPS [4] (Continuation-Passing Style). Cette fonction, d´finie figure 7.1, est param´tr´e par une
                                              e
continuation k. Pour les expressions instantan´es (telles que 0 e), la fonction de traduction C[e]
          e                                                                              e
est utilis´e. Cette fonction propage l’information de traduction. Les traductions de d´finitions
                          e e
de processus sont param´tr´es par des variables κ.
  C[x] = x        C[c] = c        C[(e1 , e2 )] = (C[e1 ], C[e2 ])      C[e1 e2 ] = C[e1 ] C[e2 ]

  C[λx.e] = λx.C[e]          C[rec x = e] = rec x = C[e]             C[pre e] = pre C[e]

  C[pre ?e] = pre ?C[e]            C[emit e1 e2 ] = emit C[e1 ] C[e2 ]

  C[signal x default e1 gather e2 in e] = signal x default C[e1 ] gather C[e2 ] in C[e]

  C[process e] = process Λκ.Cκ [e]
                       e                                e
      Il n’y a pas de s´quence en Lk puisqu’elle est cod´e avec les continuations. La branche droite
                                                  e
                                            7.2. S´mantique                                          113

                                                   e                                     e
de e1 ;e2 est traduite avec la continuation k. Le r´sultat de cette traduction est utilis´ comme
continuation de la branche gauche.
    Pour le present, nous traduisons les deux branches avec la continuation k. Pour les lieurs
                                  e
await/in et signal/in, il faut v´rifier que le nom qui est introduit ne capture pas une variable
dans la continuation.
                                                                        e             e
    Enfin, voyons la traduction du let/and/in. L’instruction split d´clenche l’ex´cution des
deux branches e1 et e2 . Ces branches ont pour continuation une instruction join qui attend la
                                                                                           e
terminaison de l’autre branche. La continuation des join est une instruction def qui r´cup`re e
          e                       e
instantan´ment les valeurs calcul´es par les deux branches.


7.2      e
        S´mantique
            e              e                                     e
    Nous pr´sentons une s´mantique petits pas de Lk . Cette s´mantique utilise une approche
similaire a Glouton. Elle se pr´sente en deux ´tapes. Pendant l’instant, il y a un ensemble C
          `                      e                e
d’expressions a ex´cuter. Lorsqu’une expression de C est bloqu´e sur le test d’un signal, elle est
              ` e                                               e
enregistr´e dans une file d’attente de W. A
         e                                 ` la fin d’instant, lorsque C est vide, les expressions
present et await qui sont dans W sont trait´es pour pr´parer la r´action de l’instant suivant.
                                               e         e          e
        e        e
    La r`gle de r´action d’un instant est de la forme :

                                    S, J, W        C =⇒ S , J , W            C

                                      e                        e             e e
S est l’environnement de signaux d´fini comme dans les s´mantiques pr´c´dentes. J est un
                             e                                                             e
environnement qui est utilis´ pour la synchronisation de la terminaison des branches parall`les.
           `
Il associe a chaque adresse j, un compteur cpt qui indique le nombre de branches parall`les e
                                                                          e
encore actives et une paire de valeurs vopt qui contient la valeur calcul´e par chaque branche.
vopt est ´gal a ⊥ tant que le calcul de la branche parall`le n’est pas termin´.
         e    `                                          e                   e

                    J ::= [. . . , (cpt, (vopt , vopt ))/j, . . .]           vopt ::= v | ⊥

Nous d´finissons les fonctions d’acc`s J cpt , J v , J v1 et J v2 dans un environnement J tel que si
       e                           e
J(j) = (n, (v1 , v2 )) alors :

                J cpt (j) = n       J v (j) = (v1 , v2 )        J v1 (j) = v1        J v2 (j) = v2

                              ` e                                                e
   L’ensemble des expressions a ex´cuter et l’ensemble des files d’attentes sont d´finis par :

                         C ::= ∅ | < k, v >, C                  W ::= [. . . , C/n, . . .]

Les informations enregistr´es dans C et W sont des paires : (expression k, valeur v). k est
                           e
             ` e                 e                             e
l’expression a ex´cuter et v le r´sultat de l’expression calcul´e avant k. Nous devons toujours
garder la valeur v afin de coder le let/and/in.
        e                               e
    La r´action d’un instant est donc d´finie par :

              S, J, W     C =⇒ S , J , W            O = next(S ) O               W =⇒eoi W | C
                                    S, J, W       C =⇒ S , J , W             C
114                                               7. Lk

    D´taillons chaque ´tape de la r´action d’un instant. La r´action pendant l’instant S, J, W
      e               e            e                         e
C =⇒ S , J , W est d´finie par la r´action de toutes les instructions qui sont dans C. On a
                        e             e
ainsi :


                                      S, J, W     ∅ =⇒ S, J, W

                             S, J, W < e, v > −→ S1 , J1 , W1 C1
              W2 , C2 = wakeU p(S#S1 , W1 )   S1 , J1 , W2 C, C1 , C2 =⇒ S , J , W
                                S, J, W     < e, v >, C =⇒ S , J , W
Comme pour Glouton, la fonction wakeU p d´bloque dans W1 les expressions associ´es a un
                                                   e                                        e `
       e               e                                     e
signal ´mis par la r´action de e. La fonction wakeU p est d´finie au chapitre 6.3.1 (page 98).
         e                                     e
    La r´action de chaque expression est d´finie figures 7.2 et 7.3. Commentons ces r`gles :e
           e                 e                                                          e
    – La r´action de e.k ´value l’expression ML e en une valeur v , et demande l’ex´cution de
      la continuation k dans l’instant. k est enregistr´ avec la valeur v dans C.
                                                        e
                                      e             e
    – L’instruction present ex´cute instantan´ment sa branche then si le signal test´ est      e
         e                                                                 e
      pr´sent. Si le signal est absent, l’instruction present est enregistr´e dans la file d’attente
      de n.
    – Le comportement de await/immediate est similaire au present.
    – La construction await/in se place toujours en attente dans W. Elle ne peut pas se r´duire
                                                                                             e
      avant la fin d’instant.
               e                    e                        e e
    – run e.k ´value e en une d´finition de processus param´tr´e par la variable κ. Cette variable
                        e
      κ est substitu´e par la continuation du run (k) dans le corps du processus. Le nouveau
      processus est alors plac´ dans C.
                                  e
           e
    – La r`gle pour signal alloue un nouveau signal n dans S et substitue x par n dans la
                                                        e     e e
      continuation. Cette nouvelle continuation doit ˆtre ex´cut´e dans l’instant courant.
                e
    – split cr´e un nouveau point de synchronisation j dans l’environnement J. Ce point est
      initialis´ a (2, ⊥, ⊥). Le chiffre 2 indique que les deux branches du parall`le sont actives
               e`                                                                  e
      et les ⊥ que les valeurs de terminaison ne sont pas encore calcul´es.
                                                                         e
                                                      e
      La variable de synchronisation x est substitu´e par j dans les deux continuations de split.
                                        e                 e
      Ainsi les deux branches parall`les partagent le mˆme point de synchronisation dans J.
                                                  ` e
      Finalement, les deux continuations sont a ex´cuter dans l’instant courant.
                                                                             e
    – L’expression join indique la terminaison d’une branche d’un parall`le. On applique donc
                                                               e e
      la fonction join sur l’environnement J. Cette fonction d´cr´mente le compteur de branches
                     e                       e
      actives et m´morise la valeur calcul´e par la branche. L’environnement J est donc ´gal ae   `
      join(J, j, i, v) si et seulement si :
                                   
                                    J(j )                            si j = j
                     ∀j : J (j ) =   (J cpt (j) − 1, (v, J v2 (j)))   si j = j et i = 1
                                    cpt
                                     (J (j) − 1, (J v1 (j), v))       si j = j et i = 2

                                                   u                                      u
        Les deux cas du join distinguent le cas o` il reste une branche active du cas o` les deux
                             e        e                                               `
        branches ont termin´ leur ex´cution. Dans le premier cas, il n’y a plus rien a faire apr`se
                                                       e e                                      e
        le join. Dans le second, la continuation est ex´cut´e en transmettant les valeurs calcul´es
                                         e
        par les deux branches du parall`le.
                                                            e                           e
      – Enfin, l’instruction def qui se trouve toujours derri`re un join est donc associ´e avec une
        paire de valeurs. Ces valeurs substituent x et y dans la continuation k.
                                       e
                                 7.2. S´mantique                                               115




                                      e/S ⇓ v /S
                    S, J, W     < e.k, v > −→ S , J, W      < k, v >


                                e/S ⇓ n/S       n∈S
    S, J, W      < present e then k1 else k2 , v > −→ S , J, W            < k1 , () >


          e/S ⇓ n/S        n∈S         self = present n then k1 else k2
S, J, W      < present e then k1 else k2 , v > −→ S , J, W + [< self , v >/n]              ∅


                                e/S ⇓ n/S       n∈S
          S, J, W    < await immediate e.k, v > −→ S , J, W            < k, () >


             e/S ⇓ n/S          n∈S       self = await immediate n.k
   S, J, W      < await immediate e.k, v > −→ S , J, W + [< self , v >/n]              ∅


                       e/S ⇓ n/S       self = await n(x) in k
     S, J, W        < await e(x) in k, v > −→ S , J, W + [< self , v >/n]          ∅


                 e/S ⇓ process Λκ.kbody /S         k = kbody [κ ← k]
                S, J, W       < run e.k, v > −→ S , J, W     < k , () >


                        e1 /S ⇓ v1 /S1 e2 /S1 ⇓ v2 /S2
          n ∈ Dom(S2 ) S = S2 [(v1 , v2 , (false, v1 ), ∅)/n] k = k[x ← n]
S, J, W     < signal x default e1 gather e2 in k, v > −→ S , J, W               < k , () >



                                          e
                              Fig. 7.2 – R´action de Lk .
116                                                 7. Lk




         j ∈ Dom(J)        J = J[(2, (⊥, ⊥))/j]              k1 = k1 [x ← j]           k2 = k2 [x ← j]
            S, J, W    < split λx.(k1 , k2 ), v > −→ S, J , W               < k1 , () >, < k2 , () >


                               J = join(J, j, i, v)           J   cpt (j)   >0
                          S, J, W       < join j i.k, v > −→ S, J , W              ∅


                    J = join(J, j, i, v)       J   cpt (j)   =0        J v (j) = (v1 , v2 )
                    S, J, W   < join j i.k, v > −→ S, J , W                 < k, (v1 , v2 ) >


                                        k = k[x ← v1 , y ← v2 ]
               S, J, W    < def x and y in k, (v1 , v2 ) > −→ S, J, W                  < k , () >



                                                e
                                    Fig. 7.3 – R´action de Lk .


           e                          e                             e
    Nous d´finissons maintenant la r´action de fin d’instant. Cette ´tape commence par le calcul
                               e                                                             e
du statut et des valeurs associ´es aux signaux avec la fonction next(S). Cette fonction est d´finie
chapitre 3.3.2 (page 51). Puis, les expressions pr´sentes dans W sont parcourues pour construire
                                                  e
les ensembles C et W du d´but de l’instant suivant.
                            e
                                    O      < e, v > −→eoi W | C               O     W =⇒eoi W | C
        O    ∅ =⇒eoi W | C                    O     < e, v >, W =⇒eoi W , W | C , C

                                          e                         e        `
Seules les expressions qui testent la pr´sence d’un signal sont pr´sentes a la fin d’instant car
                             e    e                               e        e
toutes les autres peuvent ˆtre r´solues pendant l’instant. Les r`gles de r´actions pour chacune
                        e
des expressions sont d´finies figure 7.4.
         e                                          ` e        `
     La r´action de present donne la branche k2 a ex´cuter a l’instant suivant car le signal ne
           e       e                               ee e                                e
peut pas ˆtre pr´sent sinon l’expression aurait ´t´ r´duite pendant l’instant. De mˆme pour
                                         e
await/immediate, l’expression reste n´cessairement en attente.
                               e
     Le await/in teste la pr´sence du signal. Si le signal est absent, il reste en attente. Mais
           e                                         e
s’il est pr´sent, il substitue x par la valeur associ´e au signal dans k. Cette continuation sera
   e e `
ex´cut´e a l’instant suivant.


7.3                                    o
       Ajout des constructions de contrˆle
                               e
     Comme pour Glouton, la s´mantique de Lk ne garde pas la structure du terme pendant
     e                                 e       e         e
l’ex´cution. Nous sommes donc confront´s au mˆme probl`me d’implantation du do/when et
du do/until (voir chapitre 6.4). Il faut pouvoir retrouver le contexte de suspension et de
   e
pr´emption de chaque expression.
                                                                o
                           7.3. Ajout des constructions de contrˆle                            117




                   O    < present n then k1 else k2 , v > −→eoi ∅ | < k2 , () >


            O    < await immediate n.k, v > −→eoi < await immediate n.k, v > | ∅


                                             O(n) = (false, v )
                  O    < await n(x) in k, v > −→eoi < await n(x) in k, v > | ∅


                                 O(n) = (true, v )          k = k[x ← v ]
                          O     < await n(x) in k, v > −→eoi ∅ | < k , () >



                                          e
                              Fig. 7.4 – R´action de fin d’instant de Lk .


    La solution que nous proposons ici est d’introduire un environnement T qui conserve l’im-
                                                      e
brication des constructions de suspension et de pr´emption du programme et d’annoter les
                                 e                                               o
expressions du langage par les ´tiquettes de T . Nous appelons arbre de contrˆle l’environne-
                                                           e
ment T car l’imbrication des do/when et des do/until d´finit un arbre n-aire.
    Nous ajoutons au langage Lk les nouvelles expressions start_when et start_until qui
     e             e                       oe         e
repr´sentent l’entr´e dans un bloc contrˆl´. Leur ex´cution pendant l’instant ajoute un nœud
                     o         e         e
dans l’arbre de contrˆle. Les r`gles de r´action pendant l’instant des autres expressions ne sont
           e                                      e
pas modifi´es. Le changement se trouve dans la r´action de fin d’instant. Au lieu de construire les
ensembles C et W pour le prochain instant, les expressions s’enregistrent dans l’environnement
                                                                                     e
T pour retrouver la structure du programme. Nous pouvons alors effectuer la pr´emption et
                        ` e        `                                         oe            e
trouver les expressions a ex´cuter a l’instant suivant. La fin d’un bloc contrˆl´ est marqu´e par
    e
l’ex´cution d’une expression end_when ou end_until.
             c          e
    Commen¸ons par d´finir l’environnement T avant de voir comment modifier la s´mantiquee
Lk pour ajouter le do/when et le do/until.

  e
D´finition 6 (arbre de contrˆle)  o
Un arbre de contrˆle T est une fonction qui a un nom ctrl associe un quintuplet (Kind, n, C, ctrl, F)
                 o                          `
que nous appelons nœud :

                       T    ::= [ . . . , (Kindi , ni , Ci , ctrli , Fi )/ctrli , . . . ]
                       Kind ::= When | Until(λx.k)
                       F    ::= ∅ | ctrl, F

Kind indique la nature du nœud : When s’il est issu d’un do/when ou Until(λx.k) pour un
                                  e                                            e
do/until. Dans le cas de la pr´emption, λx.k est la fonction de traitement d’´chappement.
Le second ´l´ment du quintuplet n est le nom du signal sur lequel porte le contrˆle. C est un
           ee                                                                   o
ensemble d’expressions Lk qui d´pendent de ce nœud de contrˆle. Enfin ctrl et F servent a
                                   e                              o                         `
coder la structure d’arbre. ctrl est le nœud p`re et F est l’ensemble des fils.
                                              e
118                                                   7. Lk

   Les fonctions T Kind , T n , T C , T ctrl et T F sont les fonctions d’acc`s a chacune des composante
                                                                            e `
d’un nœud.

   La fonction new node(T, ctrl, Kind, n) ajoute un nouveau nœud dans l’environnement T .
                                                         e                     ee
Ce nœud est un fils de ctrl. La fonction retourne ctrl l’´tiquette du nœud cr´´ et le nouvel
environnement T . Dans T , le nœud ctrl est ajout´ et le champ T F (ctrl) est modifi´.
                                                 e                                 e

 ctrl , T = new node(T, ctrl, Kind, n)
                                  
                                   T (ctrl ) si ctrl = ctrl et ctrl = ctrl
 si ctrl ∈ Dom(T ) et T (ctrl ) =   (Kindctrl , nctrl , Cctrl , ctrlctrl , (Fctrl , ctrl )) si ctrl = ctrl
                                    (Kind, n, ∅, ctrl, ∅) si ctrl = ctrl
                                  

      Nous introduisons les notations suivantes :
      – Si T est en arbre et ctrl est un nœud, on notera T − ctrl le r´sultat de la suppression du
                                                                        e
        sous-arbre de racine ctrl de l’arbre T .
                                                                                          `
      – L’op´ration T + [< k, v >/ctrl] ajoute la paire < k, v > a l’ensemble T C (ctrl). A l’inverse,
             e                                                   `
        l’op´ration T − [T
            e              C (ctrl)/ctrl] met l’ensemble C du nœud ctrl a vide.
                                                                          `
      ´                                          e `                                        e
      Etudions maintenant les modifications apport´es a Lk et les nouvelles expressions ajout´es.

              k ::=      ...
                       | presentctrl e then k else k | await immediatectrl e.k
                       | awaitctrl e(x) in k | runctrl e.k
                       | start untilctrl e (λctrl.k) (λx.k) | start whenctrl e (λctrl.k)
                       | end until ctrl.k | end when ctrl.k | whenctrl e ctrl

              e ::=      . . . | process Λκ, ctrl.k

                  e         `                         e          e
Les expressions r´agissant a la fin d’instant doivent ˆtre annot´es par leur nœud de contrˆle.  o
                                  ıtre                    o
L’expression run doit aussi connaˆ son nœud de contrˆle pour transmettre cette information
                         e
au processus qu’elle ex´cute. Enfin les expressions start_until, end_until et start_when,
                      e                   e
end_when sont ajout´es pour marquer le d´but et la fin des do/until et des do/when. L’expres-
                    e                  e
sion when est ajout´e pour garder l’ex´cution du corps des do/when.
                                            e e                            o
    Les deux expressions start_ sont param´tr´es par e le signal de contrˆle et (λctrl.k) le corps
                           o                     e                 e e
de la construction de contrˆle. start_until est ´galement param´tr´ par (λx.k) la fonction de
              e               e                    e
traitement d’´chappement. L’´tiquette du nœud p`re se trouve en indice des deux expressions.
                      e e
    Afin de pouvoir g´n´rer ces nouvelles expressions, il faut modifier la fonction de compilation.
          e           e e                      o                                      e
Elle doit ˆtre param´tr´e par le nœud de contrˆle en plus de la continuation. Sa d´finition est
      e
donn´e figure 7.5.
    La traduction du do/when commence par l’expression start_when et la traduction du corps
                                       o
se fait dans un nouveau nœud de contrˆle ctrl avec la continuation end_when. La compilation du
                    e      e                                                       e
do/until suit le mˆme sch´ma, elle ajoute en plus la compilation du traitement d’´chappement.
         e               e                              e                                  e
    La s´mantique de la r´action pendant l’instant est d´finie figure 7.6. Nous donnons les r`gles
                                                                                 e
seulement pour le run et les nouvelles expressions car les autres restent inchang´es.
                                          e                                             o
    – Le run fournit au processus qu’il ex´cute sa continuation et son contexte de contrˆle.
            e                         e
    – L’ex´cution de start_until cr´e un nœud Until dans l’environnement T et demande
           e                                      ee          e
      l’ex´cution de son corps dans lequel ctrl a ´t´ remplac´ par ctrl .
                                                                o
                           7.3. Ajout des constructions de contrˆle                                        119




    Ck,ctrl [run e] = runctrl C[e].k

    Ck,ctrl [present e then e1 else e2 ] = presentctrl C[e] then Ck,ctrl [e1 ] else Ck,ctrl [e2 ]

    Ck,ctrl [await immediate e] = await immediatectrl C[e].k

    Ck,ctrl [await e1 (x) in e2 ] = awaitctrl C[e1 ](x) in Ck,ctrl [e2 ]          avec        x ∈ f v(k)

    Ck,ctrl [do e1 when e] = start whenctrl C[e] (λctrl .Cend when           ctrl .k,ctrl   [e1 ])
    avec ctrl ∈ f v(k) ∪ f v(e1 )

    Ck,ctrl [do e1 until e(x) -> e2 done] =
      start untilctrl C[e] (λctrl .Cend until     ctrl .k,ctrl   [e1 ]) (λx.Ck,ctrl [e2 ])
    avec ctrl ∈ f v(k) ∪ f v(e1 )

    C[process e] = process Λκ, ctrl.Cκ,ctrl [e]



                                                                             o
         Fig. 7.5 – Traduction de ReactiveML vers Lk avec structures de contrˆle.


                                                                                       e
   – L’expression end_until supprime le nœud ctrl de l’environnement T et demande l’ex´cution
     sa continuation.
           e                            e                                       e e
   – L’entr´e dans un bloc do/when cr´e un nœud When. Le corps n’est pas ex´cut´ instan-
        e                      e                      o                  e
     tan´ment. Il est enregistr´ dans l’arbre de contrˆle. Il est remplac´ par une expression
                                           ` e                  e
     when dans l’ensemble des expressions a ex´cuter instantan´ment.
                                                 e           e
     L’expression when attend que le signal soit ´mis pour d´bloquer le corps du do/when qui
                                 o
     attend dans l’arbre de contrˆle.
                            ` e          e                              e               e
   Il nous reste maintenant a d´finir la r´action de fin d’instant. Cette ´tape est compl`tement
   e                                  e
diff´rente du cas sans suspension ni pr´emption. Elle commence par le calcul de l’environnement
O = next(S). Puis toutes les instructions de W sont parcourues pour reconstruire l’arbre du
programme avec une r´action T, O W =⇒eoi T . Enfin, les pr´emptions sont effectu´es et le
                       e                                         e                      e
                                 ` e                  e
nouvel ensemble des expressions a ex´cuter est calcul´ avec la fonction next(O, T, ctrl).
   La r´action T, O
       e                W =⇒eoi T est d´finie par les deux r`gles suivantes :
                                       e                   e


                                       T, O   < e, v > −→eoi T              T ,O      W =⇒eoi T
           T, O    ∅ =⇒eoi T                      T, O     < e, v >, W =⇒eoi T


      e                                       e                                     e     e
Les r`gles pour chaque expressions sont donn´es figure 7.7. Elles calculent les mˆmes r´sidus
               e         e                                                        e
que ceux donn´s par les r`gles de la figure 7.4. Mais les expressions sont ici plac´es dans T au
lieu d’ˆtre mises dans W ou C.
        e
                       ` e
    Il nous reste enfin a d´finir la fonction next(O, T, ctrl) qui retourne un nouvel arbre T et
l’ensemble C des expressions a ex´cuter par le sous-arbre ´tiquet´ par ctrl.
                             ` e                          e       e
120                                                  7. Lk




               e/S ⇓ process Λκ, ctrl .kbody /S          k = kbody [κ ← k, ctrl ← ctrl]
                    S, J, T, W      < runctrl e.k, v > −→ S , J, T, W     < k , () >


      e/S ⇓ n/S       ctrl , T = new node(T, ctrl, Until(λx.k ), n)          k = k[ctrl ← ctrl ]
      S, J, T, W     < start untilctrl e (λctrl .k) (λx.k ), v > −→ S , J, T , W        < k , () >



            S, J, T, W      < end until ctrl.k, v > −→ S, J, T − ctrl, W         < k, () >


         e/S ⇓ n/S        ctrl , T = new node(T, ctrl, When, n)          k = k[ctrl ← ctrl ]
                                   T = T + [< k , () >/ctrl ]
  S, J, T, W       < start whenctrl e (λctrl .k), v > −→ S , J, T , W       < whenctrl n ctrl , () >


                          n∈S          W = W + [< whenctrl n ctrl , v >/n]
                      S, J, T, W     < whenctrl n ctrl , v > −→ S, J, T, W       ∅


                       n∈S         C = T C (ctrl )     T = T − [T C (ctrl )/ctrl ]
                      S, J, T, W     < whenctrl n ctrl , v > −→ S, J, T , W      C



             S, J, T, W      < end when ctrl.k, v > −→ S, J, T − ctrl, W         < k, () >



                                  e                                     o
                      Fig. 7.6 – R´action de Lk avec structures de contrˆle.
                                                                    o
                               7.3. Ajout des constructions de contrˆle                       121




             T, O        < presentctrl n then k1 else k2 , v > −→eoi T + [< k2 , () >/ctrl]


    T, O    < await immediatectrl n.k, v > −→eoi T + [< await immediatectrl n.k, v >/ctrl]


                                              O(n) = (false, v )
           T, O     < awaitctrl n(x) in k, v > −→eoi T + [< awaitctrl n(x) in k, v >/ctrl]


                                    O(n) = (true, v )      k = k[x ← v ]
                     T, O     < awaitctrl n(x) in k, v > −→eoi T + [< k , () >/ctrl]


                  T, O     < whenctrl n ctrl , v > −→eoi T + [< whenctrl n ctrl , v >/ctrl]



                         e                                                     o
             Fig. 7.7 – R´action de fin d’instant de Lk avec structures de contrˆle.

 next(O, T, ctrl) =
   match T Kind (ctrl) with
    | When →
      if T n ∈ O then
          T, ∅
      else
          Set T := T , C := ∅ in
          forAll ctrl sous-arbre de ctrl do
             T , C := next(O, T , ctrl ) ;
             C := C , C ;
          done ;
          T + [C /ctrl], < whenT ctrl (ctrl) T n (ctrl) ctrl, () >
    | Until(λx.k) →
      if T n ∈ O then
          T − ctrl, < k[x ← O v (n)], () >
      else
          Set T := T , C := ∅ in
          forAll ctrl sous-arbre de ctrl do
             T , C := next(O, T , ctrl ) ;
             C := C , C ;
          done ;
          T − [T C (ctrl)/ctrl], (T C (ctrl), C )
                           e                        `
La fonction commence par d´terminer le traitement a appliquer en fonction du type du nœud.
                                            o
Si c’est un nœud When et le signal qui contrˆle le nœud est absent, cela signifie que ce sous-
122                                              7. Lk

               ee      e              e                                  `
arbre n’a pas ´t´ activ´ pendant la r´action. Dans ce cas, il n’y a rien a faire. Si le signal est
   e                                e
pr´sent, la fonction next est appel´e sur chacun des sous-arbres du nœud ctrl. Puis, toutes
                 ` e                                                          e
les instructions a ex´cuter par le nœud ctrl et ses sous-arbres sont enregistr´s dans l’arbre de
      o                                 e
contrˆle. L’expression when qui peut d´bloquer ce nœud est rendue.
                                                      e                            e
     Dans le cas d’un nœud Until, si le signal est pr´sent, il faut effectuer la pr´emption. Le
sous-arbre ctrl est supprim´ de l’arbre de contrˆle (T − ctrl) et l’expression de traitement
                              e                   o
  e                         e                    ` e
d’´chappement est retourn´e comme expression a ex´cuter. Si le signal est absent, la fonction
               e
next est appel´e sur tous les sous-arbres.


Attente passive inter-instant
     Dans cette version de la s´mantique de Lk , les files d’attente de W ne sont pas conserv´es
                                e                                                                 e
              `                       e
d’un instant a l’autre. Donc cette s´mantique n’implante pas l’attente passive inter-instant. Par
                           e                                  e          e
contre la version de la s´mantique sans suspension ni pr´emption g`re l’attente passive inter-
                                                         e
instant. Dans l’implantation, pour les expressions d´finies en dehors de toute construction de
      o
contrˆle, nous implantons l’attente passive inter-instant mais pas pour les autres.
                                                                                      o
     Une solution pour avoir de l’attente inter-instant avec les instructions de contrˆle est de dis-
tribuer l’environnement W dans chaque nœud de T . Ainsi, les files d’attente prennent en compte
                                             o                                                e
le signal attendu et le contexte de contrˆle dans lequel elles se trouvent. Un des inconv´nients
                                        e                                     u
majeurs de cette approche vient de l’´mission de signaux : elle est plus coˆteuse. En effet, pour
  e
d´bloquer les instructions en attente, il faut parcourir la structure de T alors que dans notre
                e                                                 e `
version de la s´mantique, il y a une seule file d’attente associ´e a un signal.
                                                                                e
     D’autres questions se posent avec cette approche. Par exemple, faut-il d´bloquer les instruc-
tions qui sont en attente sous des nœuds When suspendus ? Si oui, lorsque le nœud est r´activ´e     e
           e                      e                                       e
dans le mˆme instant alors l’ex´cution des expressions est instantan´e. Mais lorsque le nœud
                e
n’est pas activ´ dans l’instant, cela fait perdre l’information d’attente. Maintenant, si les expres-
                                            e                                                 e
sions en attente sous un When sont laiss´es dans les files d’attente, lorsque le corps est r´activ´  e
         e                                          ` e
il faut v´rifier qu’il n’y a pas de files d’attente a d´bloquer.


7.4     Conclusion
                                    e    e            `
    Dans ce chapitre, nous avons pr´sent´ le langage a base de continuation L k . C’est ce langage
              e           e
qui est utilis´ pour l’ex´cution efficace de ReactiveML. Il permet d’en implanter toutes les
constructions.
                e                 e
    La difficult´ principale de la s´mantique de Lk , comme pour Glouton, vient des construc-
                o
tions de contrˆle. Elles demandent de concilier deux aspects contradictoires. D’une part, pour
e      e e                      e
ˆtre ex´cut´e efficacement, la r´action du programme doit destructurer le terme afin d’avoir un
    e                         ` e                                                      e
acc`s direct aux expressions a ex´cuter. D’autre part, pour pouvoir effectuer les op´rations de
                  e
suspension et pr´emption, il faut garder la structure du programme. Ainsi, nous sommes oblig´s  e
d’exprimer du partage entre les ensembles d’expressions a ex´cuter ou en attente (C et W) et
                                                           ` e
                  o
l’arbre de contrˆle (T ).
                                                            e
    Enfin, nous pouvons remarquer que pour avoir une ex´cution plus efficace, nous pouvons
implanter directement des expressions qui ne sont pas dans le noyau du langage. Par exemple,
                                    e
l’expression let x = e1 in e2 peut ˆtre traduite directement avec une expression def sans avoir
besoin de split et join.
                                     7.4. Conclusion                                      123

 e   e
R´sum´
                                     e    e     e                                 `
    Dans ce chapitre, nous avons pr´sent´ la s´mantique du langage Lk qui est a la base de
                                                                  `
l’implantation la plus efficace de ReactiveML. Lk est un langage a base de continuations dans
lequel nous savons traduire toutes les constructions du noyau de ReactiveML.
                                 e                         e
    Comme pour Glouton, la s´mantique de Lk est bas´e sur l’utilisation de files d’attentes
qui permettent l’implantation de l’attente passive intra-instant.
                                                      e
    Pour l’implantation de la suspension et de la pr´emption, nous introduisons la structure
                 o                   o                      `
d’arbre de contrˆle. L’arbre de contrˆle permet d’associer a chaque expression son contexte de
                    e
suspension et de pr´emption.
                                        Chapitre 8

                                   Implantation

                 e                                 e                          e e           a
    Ce chapitre d´crit comment nous passons de la s´mantique Lk du chapitre pr´c´dent jusqu’`
                                        c            e              e
l’implantation en Ocaml. Nous commen¸ons par pr´senter les probl`mes dans la compilation
de ReactiveML vers Lk . Puis nous expliquons comment implanter les expressions de Lk par un
                                                                      e
jeu de combinateurs dans un langage purement fonctionnel. Enfin nous d´crivons l’implantation
efficace de ces combinateurs en Ocaml.
                                             e `       e                        e
    La seconde partie du chapitre est consacr´e a la pr´sentation d’une biblioth`que pour la
                 e
programmation r´active en Ocaml et ses deux implantations.


8.1       Compilation vers Lk
    Le compilateur rmlc 1 que nous avons d´velopp´ type les programmes, s´pare les expres-
                                              e      e                          e
       e                                  e                          e
sions r´actives des expressions instantan´es et traduit les parties r´actives en L k . La sortie du
                                      u                                     e
compilateur est un ficher Ocaml o` les instructions de Lk sont implant´es par des fonctions
Ocaml.
                           e               e                           e
    Le typeur suit le syst`me de type d´fini chapitre 5. Pour la s´paration des expressions
          e    e                                  e
instantan´es/r´actives, nous nous basons sur les r`gles de bonne formation du chapitre 3.2. Les
                       e            e           e                      e
expressions instantan´es sont laiss´es inchang´es et les expressions r´actives sont traduites en
                 e                                             e
Lk . Lors de la s´paration, pour les expressions qui peuvent ˆtre vues comme instantan´es ou e
 e                   e                        e                             e
r´actives nous privil´gions la forme instantan´e pour qu’elles soient compil´es telles quelles vers
Ocaml.
    Pour la traduction vers Lk , nous ne pouvons pas utiliser directement la fonction Ck d´finiee
                                                      e
chapitre 7.1. Cette traduction pose en effet des probl`mes de croissance de code. Par exemple,
               e
traduisons la s´quence suivante :
  present s1 then f1() else f2();
  present s2 then g1() else g2()
La traduction ne partageant pas les continuations, si nous compilons le programme avec la
continuation k, nous obtenons le programme Lk suivant :
  present s1 then
    f1(). present s2 then g1().k else g2().k
  else
    f2(). present s2 then g1().k else g2().k
  1
      Disponible sur http://www-spi.lip6.fr/~mandel/rml.


                                                  125
126                                             8. Implantation

On constate qu’il y a quatre copies de la continuation k. Le code produit peut croˆ ıtre expo-
                                                 e        `        e
nentiellement par rapport au code source. Pour r´pondre a ce probl`me, nous introduisons la
construction bind/in qui permet d’exprimer le partage des continuations. Ainsi, le programme
  e e
pr´c´dent devient :

  bind k1 =
     bind k2 = k in
     present s2 then g1().k2 else g2().k2
  in
  present s1 then f1().k1 else f2().k1

                   e ee                 e
La taille du code g´n´r´ reste ainsi lin´aire par rapport au programme source.
      e          e                                                 e                    e
   Pr´cisons la s´mantique de cette construction bind/in. Nous ´tendons le langage L k d´fini
page 111 :
                                 k ::= . . . | bind κ = k in k
    e        e                                                             e
La r`gle de r´action de cette construction substitue la variable κ par sa d´finition :

                       S, J, W     bind κ = k1 in k2 −→ S, J, W            k2 [κ ← k1 ]

    Nous modifions maintenant la fonction de traduction Ck . Comme nous l’avons vu dans
l’exemple, il faut modifier la traduction de present :

       Ck [present e then e1 else e2 ] = bind κ = k in present C[e] then Cκ [e1 ] else Cκ [e2 ]

       e     c                         e
De la mˆme fa¸on, la composition parall`le split partage dans ses deux branches la continuation
def x and y in k :

        Ck [let x = e1 and y = e2 in e] =
             bind κ = def x and y in Ck [e] in split (λz.(C(join          z 1.κ) [e1 ], C(join z 2.κ) [e2 ]))
        avec z ∈ f v(e1 ) ∪ f v(e2 )

                                     e          e         e       e             e
    La construction bind/in peut ´galement ˆtre utilis´e pour ´viter les probl`mes de capture
de variable dans la traduction des lieurs. Par exemple, la construction await/in peut se traduire
par
               Ck [await e1 (x) in e2 ] = bind κ = k in await C[e1 ](x) in Cκ [e2 ]
                                               e
Si le domaine de nom de κ n’appartient pas au mˆme domaine de nom que x, il ne peut pas y avoir
                                             e
de capture de variable. De plus, on peut esp´rer que cette transformation aide le compilateur
                 `        e                          e                   `
du langage cible a ne pas ´tendre inutilement la port´e de la variable x a la continuation k.


8.2        Implantation des combinateurs
                                                                                     e         e
    Pour l’implantation, nous utilisons la technique introduite dans [31]. L’interpr`te est bas´
                                                                             ` e
sur un ensemble de combinateurs qui calculent les fonctions de transition a ex´cuter. Nous les
pr´sentons dans un style purement fonctionnel 2 . Nous verrons dans la section suivante comment
  e
                                                                 e
en donner une traduction efficace en Ocaml avec des traits imp´ratifs.
   2
            e                                                                    e    e
    Nous ´crivons ici du pseudo-code dans lequel nous nous autorisons des facilit´s d’´criture comme s ∈ S pour
                            e
tester si le signal s est pr´sent dans l’environnement de signaux S.
                             8.2. Implantation des combinateurs                                 127

                          e
    Nous traduisons les r`gles des figures 7.2, 7.3 et 7.4 par des fonctions de type step. Le type de
                                                                       `
ces fonctions de transition associe un environnement et une valeur a un nouvel environnement :
                     step = env × value → env
                     env = signal env × join env × waiting × current
Un environnement est le produit de signal env le type des environnements de signaux S, join env
                                                                                            `
le type des environnements J, waiting celui des fonctions qui associent une file d’attente a un
                                                                ` e
signal et current le type des listes de fonctions de transition a ex´cuter. Nous avons donc :
                       signal env    =   event ref → (α, β) event
                       join env      =   join ref → int × (value × value)
                       current       =   (step × value) list
                       waiting       =   event ref → (step × value) list
                                                   e
    L’implantation des combinateurs reprend les r`gles du chapitre 7.1. Le combinateur present
          e e                   e
est param´tr´ par le signal test´ s et les deux fonctions de transition f 1 et f2 .
 let present s f1 f2 =
     let rec f ((S, J, W, C), v) =
         if s ∈ S
         then f1 ((S, J, W, C), ())
         else
             if eoi ∈ S then (S, J, W, ((f2 , ()), C))
             else (S, J, W + [(f, v)/s], C))
     in f
 present : event ref → step → step → step
                                                                  e
f est la fonction de transition de present. Si le signal est pr´sent, la branche then (f 1 ) est
   e e                                                               `
ex´cut´e. Lorsque le signal est absent, nous distinguons deux cas. A la fin de l’instant (eoi ), la
fonction f2 est enregistr´e dans C pour ˆtre ex´cut´e a l’instant suivant. Sinon, dans le dernier
                         e                e     e e `
cas, la fonction de transition de present est enregistr´e en attente de s dans W.
                                                        e
     Il est important de remarquer que l’on enregistre directement les fonctions de transition
des expressions a ex´cuter dans C et W. Dans les autres implantations du mod`le r´actif,
                  ` e                                                                 e     e
l’information d’activation ou d’attente remonte dans la structure du terme et lorsque l’on veut
 e
r´activer une instruction, il faut reparcourir le terme. Dans certaines implantations, comme
                                                                                              e
Reflex [28], il y a des heuristiques pour essayer de minimiser les parcours, mais la qualit´ de
                   e                      ` e
ces heuristiques d´pend du programme a ex´cuter.
                                                                        o
     Dans l’implantation, la liaison des noms est faite par le langage hˆte. Par exemple, le com-
                             e e                                e `
binateur signal est param´tr´ par une fonction qui appliqu´e a un nom retourne une fonction
de transition.
 let signal e1 e2 (λs.f) ((S, J, W, C), v) =
     let n, S = n ∈ Dom(S). (n, S[(e1 , e2 , (false, e1 ), ∅)/n]) in
     let f’ = (λs.f) n in
     f’ ((S, J, W, C), ())
 signal : (event ref → step) → step
            c                        ee e                   o     e
De cette fa¸on, la substitution est d´l´gu´e au langage hˆte et ´galement l’allocation et la
 e                   e                          `
d´sallocation de la m´moire. Cette approche est a la fois plus efficace et source de moins d’er-
reurs.
128                                        8. Implantation

                                                                   e
   Implantons maintenant les constructions split, join et def pour ´tudier la composition
      e
parall`le.
 let split (λx.(f1 , f2 )) ((S, J, W, C), v) =
     let j, J = j ∈ J. (j, J[(2, (⊥, ⊥))/n]) in
     let f1 ’, f2 ’ = (λx.(f1 , f2 )) j in
     f1 ’ ((S, J , W, ((f2 ’, ()), C)), ())
 split : (join ref → step × step) → step
                                                                 e
Ce combinateur alloue un nouveau point de synchronisation j et ex´cute la branche gauche dans
                   u                       e      e e
un environnement o` la branche droite doit ˆtre ex´cut´e dans l’instant courant.
 let join j i f ((S, J, W, C), v) =
     let J = join(J, j, i, v) in
     if J cpt (j) > 0 then (S, J , W, C)
     else f((S, J , W, C), J v (j))
 join : join ref → int → step → step
                        e e                                                           e
Le combinateur join d´cr´mente le compteur de branches actives avec la fonction join d´finie
                   e e                                         e e
dans le chapitre pr´c´dent (page 114). La continuation f est ex´cut´e uniquement lorsque le
                ` e
compteur arrive a z´ro.

 let def (λ(x,y).f) ((S, J, W, C), v) =
     let f’ = (λ(x,y).f) v in
     f’ ((S, J, W, C), ())
 def : (value × value → step) → step

                                             e    e
Le combinateur def utilise la valeur v pour r´cup´rer les valeurs de x et y.
                         e                                                             ` e
    Nous implantons de mˆme les autres constructions de Lk . Il nous reste maintenant a d´finir
l’ordonnanceur qui ex´cute l’instant tant que l’ensemble C n’est pas vide, puis pr´pare le chan-
                     e                                                            e
gement d’instant.
        e            e                          e
    La r´action compl`te d’un programme est d´finie par la fonction exec :
 let rec exec (S, J, W, C) =
     match W, C with
     | W, ((f, v), C ) →
        let (S , J , W , ∅) = schedule f ((S, J, W, C ), v) in
        let L = ∪n∈Dom(W) W(n) in
        let (W , C ) = schedule eoi L (S + [()/eoi ]) J (W , C ) in
        let S = ∀n ∈ S .S [n ← (S d (n), S g (n), next(S )(n), ∅)] in
        exec(S , J , W , C )
     | ∅, ∅ → ()
 exec : env → unit
         e e             e                             e                                       a
La premi`re ´tape de la r´action d’un instant est l’ex´cution de la fonction schedule jusqu’` ce
                                ` e        `
que l’ensemble des instructions a ex´cuter a l’instant courant soit vide. Puis toutes les fonctions
en attente dans W sont r´cup´r´es et r´activ´es avec la fonction schedule eoi. Enfin, l’envi-
                          e    ee       e       e
                                                           e
ronnement des signaux de l’instant suivant S est calcul´. Lorsqu’il n’y a plus de fonctions de
transition dans W et C, l’ex´cution du programme est termin´e.
                             e                                  e
                                      e
    La fonction schedule calcule la r´action pendant l’instant en appelant toutes les fonctions
de transition pr´sentes dans C :
                e
                               8.3. Implantation en Ocaml                                  129

 let rec schedule f ((S, J, W, C), v) =
     let (S , J , W , C ) = f ((S, J, W, C), v) in
     match C with
      | (f, v), C → schedule f ((S , J , W , C ), v)
      | ∅ → (S , J , W , ∅)
 schedule : step → env × value → env

schedule eoi r´active les instructions pr´sentes dans L pour construire le nouvel environnement
                 e                       e
` e        `
a ex´cuter a l’instant suivant :

 let schedule eoi L S J (W, C) =
     match L with
      | (f, v), L →
        let (S, J, W , C ) = f ((S, J, W, C), v) in
        schedule eoi L S J (W , C )
      | ∅ → (W, C)
 schedule eoi :
     current → signal env → join env → (waiting × current) → (waiting × current)


8.3    Implantation en Ocaml
                     e                                       e e       ee e e
    Une version imp´rative plus efficace des combinateurs pr´c´dents a ´t´ r´alis´e en Ocaml.
            e
Elle est bas´e sur la remarque que la fonction de transition de chaque combinateur prend en
       e                                                        e                       e
param`tre et retourne l’environnement. L’environnement peut ˆtre directement implant´ dans
                         ee
le tas en utilisant des r´f´rences et en les modifiant physiquement. Les fonctions de transition
ont donc le type suivant :
type ’a step = ’a -> unit
                            e                           e                                   e
L’environnement est modifi´ par effet de bord. Le param`tre ’a est le type de la valeur calcul´e
                    e e
par l’instruction pr´c´dente.
             c
    Commen¸ons par l’environnement J de points de synchronisation. En Ocaml, nous pouvons
e                                             c
´crire les combinateurs split et join de la fa¸on suivante :
let split f v =
  let j = (ref None, ref None) in
  let f1, f2 = f j in
  current := f2 :: !current;
  f1 ()
val split :
  (’a option ref * ’b option ref -> unit step * unit step) -> ’c step

let join (vref1, vref2) vrefi f v =
  vrefi := Some v;
  match !vref1, !vref2 with
  | Some v1, Some v2 -> f (v1, v2)
  | _ -> ()
val join :
  ’a option ref * ’b option ref -> ’c option ref -> (’a * ’b) step -> ’c step
130                                         8. Implantation

                                    e                                     e              ee
Le combinateur split alloue la m´moire directement dans le tas en cr´ant les deux r´f´rences
         e `                           e e          ee                                    e
initialis´es a None. Le join est param´tr´ par ces r´f´rences (vref1 et vref2) et le num´ro de la
          `                     e                                           ee          e e
branche a modifier est remplac´ par vrefi, le pointeur vers une des deux r´f´rences pr´c´dentes.
                  e         `                                          e
Ainsi il a un acc`s direct a l’environnement J. Nous avons remplac´ le compteur de branches
                                           e
actives par du filtrage sur la valeur calcul´e par chacune des branches.
     Dans l’implantation de split, nous observons ´galement que l’ensemble C est implant´ par
                                                    e                                       e
la liste current. C’est une liste modifiable de fonctions de type unit step. Nous n’avons pas
`
a enregistrer le couple fonction de transition/valeur dans cette liste, car toutes les fonctions
                                            e
qui s’enregistrent dans cette liste peuvent ˆtre vues comme des fonctions de transition de type
                                                                                  e
unit step. En effet, seuls les combinateurs join et def utilisent la valeur donn´e en argument
                                                                                              e
de la fonction de transition et donc peuvent avoir des contraintes sur le type de cette derni`re.
                                        e                          e e
Le combinateur def est toujours derri`re un join. Il est donc ex´cut´ directement sans passer
                                                                e      e
par la liste current. Pour le combinateur join, soit il est plac´ derri`re une expression ML qui
    e                e
l’ex´cute instantan´ment, soit dans tous les autres cas, il attend la valeur ().
     ´                                                              e
    Etudions maintenant l’implantation des expressions instantan´es. Les expressions instan-
    e         e e                        e                                     e    e
tan´es sont s´par´es des expressions r´actives avec l’analyse que nous avons pr´sent´es au cha-
                e                                        `
pitre 3.2. Cela ´vite d’appliquer la transformation CPS a l’ensemble du code ce qui rendrait les
parties Ocaml moins efficaces.
              e                                   e
    Pour l’ex´cution d’une expression instantan´e, le calcul d’une valeur Ocaml est effectu´    e
                          e e               e                                e
et la continuation est ex´cut´e instantan´ment pour ne pas avoir de probl`me avec le join.
                                       u                e    e             o     e
Il faut faire attention au moment o` l’expression est ´valu´e. Pour contrˆler l’´valuation des
                                      e             c                 `
expressions ML, nous utilisons le m´canisme de gla¸on. Cela consiste a ajouter une abstraction
autour de l’expression. Par exemple, l’expression :
  print_string "hello"; print_newline()
traduite avec la continuation k devient :
  compute (fun () -> print_string "hello"; print_newline()) k
                                e              e
Ainsi, le message hello est affich´ lorsque l’on ´value la fonction de transition du combinateur
                                  e
compute et pas au moment de sa d´finition. Le code du combinateur est le suivant :
  let compute e f v =
    let v’ = e() in
    f v’

Remarque :
              e           e
   Il est int´ressant de d´finir les parties ML les plus grandes possibles car cela diminue
                     c                            e e        e
   le nombre de gla¸ons. Le code de l’exemple pr´c´dent est ´quivalent mais meilleur que
   celui ci :
        compute (fun () -> print_string "hello")
          (compute (fun () -> print_newline()) k)

    ´                            e                                                  e ıtresses
    Etudions maintenant la repr´sentation de l’environnement des signaux. Les id´es maˆ
sont de ne jamais manipuler explicitement l’ensemble de tous les signaux et d’avoir un acc`se
       `                                                                          e
direct a toutes les informations tel que le statut d’un signal ou sa valeur associ´e.
                                                                                      e
    La plupart des implantations de Junior utilisent des tables de hachage pour repr´senter
                                          e                                                e
l’environnement des signaux. Cette repr´sentation ajoute une indirection pour tous les acc`s.
                                8.3. Implantation en Ocaml                                      131

                                        e
Dans notre approche, les expressions acc`dent directement au signal. L’expression L k :
signal x default e1 gather e2 in k, se traduit en Ocaml par :
  fun v -> let x = new_event e1 e2 in k ()
                                                          e
Cette fonction de transition alloue la structure de donn´e qui implante le signal avec la fonction
                                            ee
new_event. Puis elle substitue x par la r´f´rence vers le signal dans la continuation.
                                                                                        e
    Ne pas maintenir l’ensemble des signaux du programme dans une structure de donn´e permet
                                             o       e   e       e             e
au Glaneur de Cellule (GC) du langage hˆte de r´cup´rer la m´moire allou´e pour les signaux
                                                            e              e
qui ne sont plus utilisables. Si l’environnement est conserv´ par l’interpr`te dans une table des
                            e    e
signaux, il faut nettoyer r´guli`rement cette table pour que les signaux inutiles ne soient plus
                                         e    e        e
accessibles et donc que le GC puisse r´cup´rer la m´moire. Certaines implantations du mod`le    e
 e
r´actif comme Simple et Reflex ont un GC pour la table des signaux. Mais utiliser directement
                     o                             e                             e
le GC du langage hˆte simplifie l’implantation, ´vite des bogues et surtout ´vite d’avoir deux
             e            e                                                e e
GC qui s’ex´cutent en mˆme temps. De plus, le GC de Ocaml [36] se r´v`le efficace.
                                          e      e
    L’implantation du type event utilis´e par d´faut dans le compilateur actuel est la suivante :
  type (’a, ’b) event_struct =
      { mutable status: int;
        mutable pre_status: int;
        mutable value: ’b;
        mutable pre_value: ’b;
        default_value: ’b;
        combine: (’a -> ’b -> ’b); }
  and (’a, ’b) event =
     (’a, ’b) event_struct * unit step list ref * unit step list ref
                             e
Le type event_struct repr´sente les informations contenues dans l’environnement de signaux
                           `
S et le type event ajoute a cet enregistrement deux files d’attentes.
    Les files d’attente de W sont directement li´es aux signaux. Ceci permet d’avoir un acc`s
                                                   e                                              e
       `                                                                   e      e
direct a la bonne file d’attente quand un test de signal ne peut pas ˆtre r´solu. Nous avons
s´par´ les files d’attente en deux : Wa pour l’attente des await qui peuvent ˆtre gard´s d’un
 e e                                                                                e        e
instant a l’autre, et Wp pour les present qui doivent ˆtre r´activ´s a la fin de l’instant.
         `                                                e    e      e `
                                                                       e              e
    Dans l’enregistrement, le statut d’un signal est un entier qui repr´sente le num´ro de l’instant
 u             eee                                          e                    e
o` le signal a ´t´ ´mis. Ainsi, la fonction qui teste la pr´sence d’un signal s’´crit :
let is_present s = s.status = !instant
val is_present : (’a, ’b) event -> bool
 u                                                                          e
o` instant est la variable globale qui compte les instants. Cette repr´sentation du statut
          e
est utilis´e dans la plupart des implantations de Junior. Elle permet de remettre le statut
                      `                                     e
de tous les signaux a la valeur absent seulement en incr´mentant le compteur d’instants. En
                                                                    e
contrepartie, la question de la limite des entiers machine se pose n´cessairement. En Ocaml, le
            e                                                             e
type int d´finit des entiers modulaires. Il ne peut donc pas y avoir de d´passement de capacit´e
                            eee             e         ee            e
mais un signal qui n’a pas ´t´ ´mis peut ˆtre consid´r´ comme pr´sent.
    De plus tester le pre d’un signal est un peu plus difficile :
let pre_is_present s =
  if is_present s
  then s.pre_status = (!instant-1)
  else s.status = !instant-1
val pre_is_present : (’a, ’b) event -> bool
132                                       8. Implantation

                                     e                                               ee
Il faut commencer par tester la pr´sence pour savoir si le champ pre_status a ´t´ mis a jour `
                ee     `                      e             e                 e e
ou pas. S’il a ´t´ mis a jour, il est compar´ avec le num´ro de l’instant pr´c´dent. Sinon nous
testons le champ status.
                  e          e e                                     u
    Nous avons ´galement r´alis´ un autre codage des signaux o` le statut est un bool´en et  e
        e           e                  e                              e e
donc r`gle le probl`me des “fausses” ´missions de l’implantation pr´c´dente. Dans cette version,
                           e                     e                                             e
tous les signaux qui sont ´mis, sont enregistr´s dans une liste to_update. Cette liste doit ˆtre
            `                                  `
parcourue a la fin de l’instant pour mettre a jour le statut et les champs pre de chaque signal.
          e                                          e                        e
Afin de r´aliser une liste de signaux de types diff´rents, nous avons utilis´ le sous-typage des
objets de Ocaml.
                                             e                                    `
    Voyons maintenant l’implantation de l’´mission de signal. Pour ne pas avoir a englober toutes
    e                                                             e
les ´missions de signaux dans un combinateur compute, nous d´finissons le combinateur emit.
              e e                           `e                             c
Il est param´tr´ par le signal et la valeur a ´mettre qui sont dans des gla¸ons et sa continuation.
Son code est le suivant :
let emit e1 e2 k =
  let (n,wa,wp) = e1() in
  let v = e2() in
  set_emit n v;
  wakeUp wa;
  wakeUp wp;
  k ()
val emit : (unit -> (’a, ’b) event) -> (unit -> ’a) -> unit step -> ’c step

                                               `e               `
Ce combinateur calcule le signal et la valeur a ´mettre. Il met a jour la structure du signal avec
la fonction set_emit. Il passe toutes les fonctions de transition de wa et wp dans current avec
la fonction wakeUp. Puis il active sa continuation.
                                          `    e
    Dans l’implantation, contrairement a la s´mantique, les expressions en attente dans wa et wp
       e     e                  e                       e                   e        `
sont r´veill´es au moment de l’´mission et les valeurs ´mises sont combin´es aussi a ce moment
 a         `                                                                   e
l` et pas a la fin d’instant. Nous faisons ce changement car au moment de l’´mission, toutes les
                e                                                                  e
informations n´cessaires pour faire ces traitements sont disponibles. Ainsi cela ´vite de devoir
traiter le signal plus tard dans l’instant. Le code de set_emit est donc :
let set_emit n v =
  if n.status <> !instant
  then
    (n.pre_status <- n.status;
     n.pre_value <- n.value;
     n.status <- !instant;
     n.value <- n.combine v n.default_value)
  else
    n.value <- n.combine v n.value
val set_emit : (’a, ’b) event_struct -> ’a -> unit

La fonction wakeUp modifie les listes d’attente et la liste current par effet de bord.
let wakeUp w =
  current := List.rev_append !w !current;
  w := []
val wakeUp : unit step list ref -> unit
                                8.3. Implantation en Ocaml                                       133

    Le code du combinateur await immediate illustre l’utilisation des files d’attente. Si le signal
      e                            e e             e
est pr´sent, la continuation est ex´cut´e instantan´ment. S’il est absent, la fonction de transition
                e
f est enregistr´e dans la file d’attente persistante (wa).

let await_immediate s k v =
  let (n, wa, _) = s() in
  let rec f () =
    if is_present n then
      k ()
    else
      wa := f :: !wa
  in f ()
val await_immediate : (unit -> (’a, ’b) event) -> unit step -> ’c step

Remarque :
                      e    e           e                                   e
      Le signal s est ´valu´ avant la d´finition de f pour qu’il soit calcul´ seulement lors de la
            e e
      premi`re ´valuation de la fonction de transition.

                                            e                                    e
     Le dernier combinateur que nous pr´sentons est present. La difficult´ de present par
          `                                   e                                 `
rapport a await immediate est qu’il faut r´activer la fonction de transition a la fin de l’instant
                     eee                                                 `
si le signal n’a pas ´t´ ´mis. Comme il n’y a pas de table de signaux, a la fin d’instant nous ne
                                                           e
pouvons pas retrouver les files d’attente qui sont associ´es aux signaux. La solution que nous
proposons est d’enregistrer les files d’attente qui testent l’absence dans une liste to_wakeup.
        `                                      `                            e
Ainsi, a la fin de l’instant, il y a seulement a parcourir cette liste pour r´veiller les instructions
en attente.

let present s k1 k2 v =
  let (n, _, wp) = s() in
  let rec f () =
    if is_present n
    then k1 ()
    else
      if !eoi
      then current := k2 :: !current
      else (wp := f :: !wp;
           to_wakeup := wp :: !to_wakeup)
  in f ()
val present :
  (unit -> (’a, ’b) event) -> unit step -> unit step -> ’c step

                  e         e
La liste wp peut ˆtre partag´e par le signal et la liste to_wakeup. Pendant un instant, elle peut
e              e                                           e    e                       ee
ˆtre enregistr´e dans to_wakeup puis, si le signal test´ est ´mis, la liste est transf´r´e dans
                                          e     e                              e
current et le combinateur present est r´activ´. Dans ce cas, il ne faut pas r´activer le present
`                                                                                         e
a la fin de l’instant. C’est effectivement ce qui ce passe car la file d’attente enregistr´e dans
                       ee                                                             e
to_wakeup est une r´f´rence vers une liste de fonctions de transition. Lors de l’´mission du
            ee                e                                          `
signal, la r´f´rence est modifi´e pour pointer vers la liste vide. Ainsi, a la fin d’instant lorsque
                                                                                ee      e
to_wakeup est parcourue, il n’y a plus les fonctions de transitions qui ont ´t´ trait´es. Cette
  e       e             ` e
m´thode ´vite d’avoir a d´poster des informations qui sont dans to_wakeup.
134                                           8. Implantation

                           e
Implantation du loop avec r´initialisation
                                                                            ` e
    Le but de cette section est d’implanter la construction loop sans avoir a r´allouer les points
                    `           e                                           e
de synchronisation a chaque it´ration. Le type de programme qui nous int´resse est le suivant :
  loop
    let x1 = await immediate s1
    and x2 = await immediate s2 in print_string "hello"
  end
                                                                 e
Nous allons proposer un traitement ad hoc du loop et modifier la d´finition du combinateur
                          e
split que nous avons donn´e page 129.
                                            e e
   La traduction en Ocaml du programme pr´c´dent est :
  loop
    (fun k ->
      let k_def (x1,x2) = compute (print_string "hello") k () in
      split
        (fun j -> (await_immediate (fun () -> s1) (join j 1 k_def),
                   await_immediate (fun () -> s2) (join j 2 k_def))))
                               e e                                                        `
Le combinateur loop est param´tr´ par une fonction qui associe une fonction de transition a
                                     e                                 e
une continuation. Cette fonction repr´sente le corps du loop. Une premi`re implantation du
                                   e             e
combinateur loop est de suivre la d´finition donn´e chapitre 3.
  let rec loop f v =
    let f’ = f (loop f) in
    f’ ()
  val loop : (unit step -> unit step) -> ’a step
                            e               e                                          e
Ici, loop est une fonction r´cursive qui ex´cute son corps avec pour continuation la d´finition
du loop 3 . On peut constater qu’` chaque it´ration la fonction de transition f’ est recalcul´e
                                  a           e                                              e
                  e
alors qu’elle ne d´pend pas de v.
     La solution que nous proposons est de commencer par calculer la fonction de transition du
                                      `
corps du loop et donc appliquer f a sa continuation. Nous donnons comme continuation la
                e                                                          e
fonction qui ex´cute la fonction de transition du corps du loop. Ainsi la d´finition du corps ne
repasse pas par le combinateur loop.
  let loop f =
    let rec f_1 = lazy (f f_2)
    and f_2 v = Lazy.force f_1 ()
    in f_2
La fonction f_1 est la fonction de transition du corps du loop. Elle est obtenue par l’application
     `                             `           e                                          e
de f a sa continuation f_2. Quant a f_2, elle ´value f_1 pour commencer une nouvelle ex´cution
                                          e
du corps du loop. Avec cette nouvelle d´finition de loop, la fonction de transition du corps est
      e
calcul´e une seule fois.
    ´                                                          e
    Etudions maintenant le combinateur split. Avec la d´finition que nous avons donn´e           e
                                                            e `
page 129, un nouveau point de synchronisation est allou´ a chaque application de la fonc-
                                   e             e                             `
tion de transition. Pour pouvoir r´utiliser le mˆme point de synchronisation a chaque appel de
                                                  e               e
la fonction de transition, il suffit d’allouer la m´moire avant la d´finition de cette fonction :
  3
                e                        e e                                            e           e
    Le type donn´ ici n’est pas celui inf´r´ par le compilateur. Le typeur de Ocaml ne g`re pas la r´cursion
                                         e
polymorphe. Pour obtenir le type souhait´, nous devons utiliser la fonction Obj.magic.
                                                             e
                      8.4. Ajout de la suspension et de la pr´emption                        135

let split f =
  let (vref1, vref2) as j = (ref None, ref None) in
  let f1, f2 = f j in
  fun v ->
    vref1 := None;
    vref2 := None;
    current := f2 :: !current;
    f1 ()
val split :
  (’a option ref * ’b option ref -> unit step * unit step) -> ’c step
                      e
L’allocation de la m´moire est faite lors du calcul de la fonction de transition quand split
           e                `                                               e       e
est appliqu´e partiellement a f. Quand la fonction de transition est appliqu´e, la m´moire est
            e        e
seulement r´initialis´e.
Remarque :
                                                        e                  e
   Si nous avons une garantie qu’un signal ne peut pas ´chapper de sa port´e, nous pouvons
   faire une implantation similaire pour le combinateur signal en allouant le signal avant la
   fonction de transition.
                           e
   Reprenons l’exemple du d´but de la section :
  loop
    (fun k ->
      let k_def (x1,x2) = compute (print_string "hello") k () in
      split
        (fun j -> (await_immediate (fun () -> s1) (join j 1 k_def),
                   await_immediate (fun () -> s2) (join j 2 k_def))))
Le combinateur loop calcule sa fonction de transition au premier instant en appliquant une
               `     e
continuation a la d´finition de son corps. Le corps de la fonction (fun k -> ...) est donc
e    e                 e                                            e`      e
´valu´. Lors de cette ´valuation le combinateur split est appliqu´ a la d´finition de ses deux
                              e        e         `
branches. Il alloue alors la m´moire n´cessaire a la synchronisation.
             e                                                   e                e
   Le probl`me de cette approche est qu’elle augmente la dur´e de vie de la m´moire allou´e.  e
                                     e      e                          e
Dans cet exemple, j n’est jamais d´sallou´ alors qu’il n’est pas utilis´ dans la partie def. Cela
     e     e                                        e                      e
peut ˆtre p´nalisant si cette partie est longue et n´cessite beaucoup de m´moire.


8.4                                      e
       Ajout de la suspension et de la pr´emption
                                       o                           e
    L’ajout des constructions de contrˆle suit les indications donn´es chapitre 7.3. Leur implan-
                                                    o
tation repose sur l’utilisation d’un arbre de contrˆle.
                         o
    Les arbres de contrˆle ont le type ctrl_tree :
   type contol_tree =
        { kind: contol_type;
          mutable alive: bool;
          mutable cond: (unit -> bool);
          mutable next: unit step list;
          mutable children: contol_tree list; }
136                                       8. Implantation

      and contol_type =
          Top
        | Until of (unit -> unit step)
        | When
                                                u          e
Le champ kind reprend les sortes de nœuds o` Top repr´sente la racine de l’arbre. Le champ
alive est utilis´ pour implanter la suppression d’un sous-arbre (T −ctrl). Lors de l’ex´cution des
                e                                                                      e
                                                        `        `
expressions end_until et end_when ce champ est mis a faux. A la fin de l’instant les branches
             e     e                         o                                  e
mortes sont ´lagu´es quand l’arbre de contrˆle du prochain instant est calcul´ avec la fonction
                                                                        o                   e
next_ctrl_tree. Le champ cond permet de tester si le signal qui contrˆle de nœud est pr´sent.
Le champ next repr´sente l’ensemble des expressions associ´es au nœud (T
                     e                                       e                C ) et children est

l’ensemble des sous-arbres (T F ).


8.5                                  e e
        Implantation sous forme API g´n´rique
                                                                                   e e
    Il existe une seconde sortie pour le compilateur que nous appelons Lco . Elle g´n`re du code
           u
Ocaml o` les combinateurs sont beaucoup plus proche des constructions du langage source.
L’ensemble de leur signature constitue une API (Application Programming Interface) similaire
`
a ce que propose Junior pour Java. Par exemple, l’expression ReactiveML :
  do
    (await s1 || await s2); emit s3
  until s4 done
se traduit en Ocaml par :
  rml_until
    (fun () -> s4)
    (rml_seq
       (rml_par
          (rml_await (fun () -> s1))
          (rml_await (fun () -> s2)))
       (rml_emit (fun () -> s3)))
                  e ee                                                                e e
Dans le code g´n´r´, nous retrouvons le combinateur rml_until qui est param´tr´ par une
                     e                                                 e        e
fonction qui doit s’´valuer en signal et son corps. Le corps est compos´ d’une s´quence (rml_seq)
                 e
qui a un parall`le (rml_par) dans sa branche gauche.
                                                 e e e
     L’avantage de cette sortie est de rester tr`s g´n´rale. Nous retrouvons la structure du pro-
                    u
gramme source o` les constructions ReactiveML sont directement traduites dans des com-
binateurs. Ainsi, en fournissant une implantation de ces combinateurs, nous pouvons tester
                                                                      `
simplement des nouvelles techniques d’ordonnancement sans avoir a modifier le compilateur.
                       e
     L’interface est d´finie dans le fichier lco_interpreter.mli. Un extrait en est donn´ fi-   e
                                                                                    e
gure 8.1. Les expressions ReactiveML sont de type ’a expr. Elles doivent ˆtre d´finies a   e     `
     e                                         e
l’int´rieur d’un processus qui bloque leur ex´cution.
                                                      e
     Le type des combinateurs reprend les types d´finis dans le chapitre 5. Nous avons seule-
             e         c                                      e
ment ajout´ des gla¸ons autour des expressions instantan´es. Les combinateurs rml_compute,
                                                c
rml_emit_val ou rml_run utilisent des gla¸ons par exemple. Les lieurs comme les combina-
teurs rml_signal_combine et rml_until_handler introduisent des noms en d´finissant dese
                             e
fonctions. Ils utilisent la mˆme technique que dans la compilation de Lk .
                                                         e e
                       8.5. Implantation sous forme API g´n´rique                            137


  type (’a, ’b) event
  and ’a expr
  and ’a process = unit -> ’a expr

  val rml_compute: (unit -> ’a) -> ’a expr
  val rml_seq: ’a expr -> ’b expr -> ’b expr
  val rml_par: ’a expr -> ’b expr -> unit expr
  val rml_pause: unit expr
  val rml_run: (unit -> ’a process) -> ’a expr
  val rml_emit_val: (unit -> (’a, ’b) event) -> (unit -> ’a) -> unit expr
  val rml_await: (unit -> (’a, ’b) event) -> unit expr
  val rml_present: (unit -> (’a, ’b) event) -> ’c expr -> ’c expr -> ’c expr
  val rml_until_handler:
      (unit -> (’a, ’b) event) -> ’c expr -> (’b -> ’c expr) -> ’c expr
  val rml_signal_combine:
      (unit -> ’b) -> (unit -> (’a -> ’b -> ’b)) ->
        ((’a, ’b) event -> ’c expr) -> ’c expr

  val rml_exec: ’a process -> ’a
  Fig. 8.1 – Extrait de lco interpreter.mli, l’interface des combinateurs ReactiveML.

Implantation de Rewrite
                       e                                   e
   Nous avons implant´ ces combinateurs en suivant la s´mantique de Rewrite [56]. Cette
 e                e           e         ee
s´mantique est bas´e sur des r`gles de r´´criture simples de la forme suivante :
                                               α
                                             −→
                                       e, S − − e , S

 u                                           e    e   `                            e     e     e
o` α est un statut de terminaison qui peut ˆtre ´gal a susp si l’expression e doit ˆtre r´activ´e
           e                              e     e    e `
dans le mˆme instant, stop si e doit ˆtre r´activ´e a l’instant suivant et term (v) si e a
       e       e                                                              e
termin´ son ex´cution en rendant la valeur v. Nous donnons quelques r`gles figure 8.2. La
 e                e         e `
s´mantique compl`te, adapt´e a ReactiveML, avec prise en compte de la partie combinatoire
                    e          e
et des signaux valu´s est donn´e en annexe B.
                                 e                                            e
    Dans l’implantation de la s´mantique Rewrite, le type ’a expr repr´sente les fonctions
                                                                            e
de transition des expressions ReactiveML. Il reprend la structure des r`gles. La fonction de
transition d’une expression calcule le statut de terminaison et la nouvelle expression. Le statut
                      e
de terminaison est d´fini par un type somme qui reprend les trois cas de terminaison possibles :
  type ’a expr = unit -> ’a status * ’a expr
  and ’a status = SUSP | STOP | TERM of ’a
                                                 e               e
    Les combinateurs traduisent directement les d´finitions donn´es figure 8.2. Par exemple,
                                         e e       e
lorsque le combinateur rml_compute est ex´cut´, il ´value l’expression e et retourne le statut
TERM et l’expression v.
  let rec rml_compute e =
    fun () ->
      let v = e() in (TERM v, rml_compute (fun () -> v))
  val rml_compute: (unit -> ’a) -> ’a expr
138                                               8. Implantation



                                                                                           α
           0    e      e/S ⇓ v/S                e/S ⇓ n/S          n∈S                  −→
                                                                                e1 , S − − e 1 , S
                    term (v)                                                           α
               e, S − − v, S
                     −→                                                        −→
                                                present e then e1 else e2 , S − − e1 , S

                                   e/S ⇓ n/S          n∈S             eoi ∈ S
                                                      susp
                                              −→
               present e then e1 else e2 , S − − present n then e1 else e2 , S

                                   e/S ⇓ n/S          n∈S             eoi ∈ S
                                                                       stop
                                                              −→
                               present e then e1 else e2 , S − − e2 , S
                                            α
                                          −→
                                  e1 , S − − e 1 , S             α = term (v)
                                                       α
                                                     −→
                                         e1 ;e2 , S − − e1 ;e2 , S

                                     term (v)                          α
                                       −→
                               e1 , S − − e 1 , S                      −→
                                                               e2 , S − − e 2 , S
                                                           α
                                                       −→
                                           e1 ;e2 , S − − e2 , S



                                               e
                                   Fig. 8.2 – S´mantique Rewrite.

                                                     e                      `
    Le combinateur rml_present commence par ´valuer le signal evt a tester, puis il construit la
                                         e             e                        e                 e e
fonction de transition qui teste sa pr´sence et l’ex´cute. Si le signal est pr´sent, e1 est ex´cut´e.
                        `                             e      e e `
Si le signal est absent a la fin de l’instant, e2 doit ˆtre ex´cut´e a l’instant suivant. Si le signal est
                                                         e
absent pendant l’instant, le statut susp est retourn´ avec la fonction de transition du present
 u          eaeee
o` evt a d´j` ´t´ ´valu´. e
  let rml_present evt e1 e2 =
    fun () ->
      let n = evt() in
      let rec self () =
       if is_present n
       then e1 ()
       else
         if !eoi
         then (STOP, e2)
         else (SUSP, self)
    in self ()
  val rml_present: (unit -> (’a, ’b) event) -> ’c expr -> ’c expr -> ’c expr
        e           e                                    e                                    e
    L’ex´cution en s´quence de e1 et e2 commence par l’ex´cution de e1. Puis, si e1 est termin´e,
    e                                                e      e             e       e
l’ex´cution de e2 peut commencer. Sinon, e2 est gard´e en s´quence derri`re le r´sidu de e1.
  let rec rml_seq e1 e2 =
    fun () ->
      match e1 () with
                                                          e e
                        8.5. Implantation sous forme API g´n´rique                             139

      | TERM _, _ -> e2 ()
      | (SUSP | STOP) as alpha, e1’ -> (alpha, rml_seq e1’ e2)
  val rml_seq: ’a expr -> ’b expr -> ’b expr
                             e                                         e
   Cette implantation de la s´mantique Rewrite permet de comparer les s´mantiques efficaces
            `                       ıf.         e
par rapport a un ordonnancement na¨ Cela permet ´galement d’avoir un point de comparaison
avec Junior qui a une implantation similaire.

Implantation de Lk
                    e                 e
     Nous avons ´galement implant´ une version de Lk dans ces combinateurs. La technique
       e                                             `     e
utilis´e est d’embarquer la fonction de compilation a l’int´rieur des expressions pour qu’elle soit
e      e                                  e e
´valu´e au moment du run et qu’elle g´n`re la fonction de transition. C’est une approche de
type staging [101].
                                           e e                                           o
     Ici, tous les combinateurs sont param´tr´s par leur continuation et le nœud de contrˆle dont
      e
ils d´pendent. Ils ont la forme suivante :
  let combinator =
    fun k ctrl ->
      fun v -> ...
                            e
Ainsi, le type ’a expr est d´fini par :
  type ’a expr = ’a step -> contol_tree -> unit step
  and ’a step = ’a -> unit
                                                                 e
Le type ’a step est celui des fonctions de transition. Il est d´fini comme dans la section 8.3.
                                        e                                  e e
Le type ’a est celui de la valeur calcul´e par la fonction de transition pr´c´dente. Comme dans
                                               e                      e
le type ’a expr, la variable de type ’a repr´sente la valeur calcul´e par l’expression, alors la
continuation de l’expression doit attendre une valeur de ce type.
                                                          e
    L’implantation repose les fonctions de transition d´finies section 8.3. Pour les expressions
qui ont une traduction simple de ReactiveML vers Lk , l’implantation est directe. C’est le cas
par exemple du combinateur rml_emit_val qui peut appeler la fonction de transition de emit :
  let rml_emit_val e1 e2 =
    fun k ctrl ->
      emit e1 e2 k
  val rml_emit_val : (unit -> (’a, ’b) event) -> (unit -> ’a) -> unit expr
   Pour implanter la construction let/and/in, il faut un peu plus de travail. En effet nous
avons vu chapitre 7.1 qu’elle se traduit en Lk avec les instructions split, join et def.
  let rml_def_and e1 e2 e3 =
    fun k ctrl ->
      let def v = e3 v k ctrl () in
      let f ((vref1, vref2) as j) =
        let f1 = e1 (join j vref1 def) ctrl in
        let f2 = e2 (join j vref2 def) ctrl in
        (f1, f2)
      in split f
  val rml_def_and : ’a expr -> ’b expr -> (’a * ’b -> ’c expr) -> ’c expr
140                                          8. Implantation

          e                                                                               e `
Dans la d´finition de def, la sous-expression e3 v est de type ’c expr. Une fois appliqu´e a k
                                                                                          e e
et ctrl, elle retourne une fonction de transition de type unit step. Cette fonction est ex´cut´e
                  `                               e
par l’application a la valeur (). La fonction f d´finit le corps du split.
                                                            e         e
    On peut remarquer que la compilation de e3 ne peut ˆtre effectu´e que lorsque la valeur v
                                  e
est connue. Donc seulement apr`s la synchronisation des deux join et pas lorsque k et ctrl
              e       e                                                   e
sont appliqu´s. De mˆme pour les expressions e1 et e2, elles sont compil´es uniquement quand
                                        e e                 e           e
la fonction de transition split est ex´cut´e. Il serait int´ressant de d´finir ces combinateurs
                                e
en MetaOCaml [71] pour sp´cifier que l’on peut appliquer la phase de compilation avant le
                        e
premier instant de l’ex´cution du programme.


8.6       Conclusion
    Nous avons pr´sent´ ici les diff´rentes implantations de ReactiveML 4 . Elle se regroupent
                     e   e           e
                                                 e                           e e
en deux familles : Lk , l’implantation de la s´mantique du chapitre pr´c´dent et Lco , la bi-
       e                                                                     e
blioth`que de combinateurs issus directement de ReactiveML. Les diff´rentes implantations
          e        e                                e
peuvent ˆtre test´es avec le compilateur rmlc. La s´lection se fait en utilisant l’option -runtime
                                                      e
suivie du nom de l’implantation. Chaque nom a le pr´fixe Lk_ ou Lco_ pour indiquer sa famille.
    Les implantations Lk sont plus efficaces car les programmes ReactiveML sont traduits
                                       ` e
dans un format qui est plus simple a ex´cuter. En revanche, l’avantage du format L co est de
proposer une interface simple qui est proche des constructions du langage source ReactiveML.
Ainsi, nous pouvons prototyper rapidement des nouveaux ordonnanceurs sans modifier le code
du compilateur, mais seulement en fournissant une nouvelle implantation des combinateurs. De
                                             e                                       e
plus, l’interface Lco peut servir de biblioth`que Ocaml pour la programmation r´active comme
le fait Junior pour Java.


 e   e
R´sum´
                  e     e              e                                             e
    Nous avons pr´sent´ dans la premi`re partie de ce chapitre l’implantation de la s´mantique
                                 ee                                                        e
Lk . La construction bind/in a ´t´ introduite pour avoir un code L k dont la taille est lin´aire
             `
par rapport a la taille du programme source. Puis une implantation des expressions de L k sous
                                                                    ee      e `
forme de combinateurs dans un langage purement fonctionnel a ´t´ propos´e. A partir de ces
                                                                  e
combinateurs, une implantation efficace en Ocaml de Lk est pr´sent´e.    e
                                                        e                            e
    Dans la seconde partie du chapitre, une biblioth`que pour la programmation r´active en
               e   e                e
Ocaml est pr´sent´e. Cette biblioth`que propose des combinateurs qui sont proche des construc-
                                                                  e e
tions de ReactiveML. Le compilateur ReactiveML peut g´n´rer du code pour cette bi-
      e
blioth`que mais il est relativement simple de les utiliser directement en Ocaml.
                            e
    De plus cette biblioth`que nous a permis de tester des implantations de ReactiveML
                        `
simplement sans avoir a modifier le compilateur.




  4
      Disponible sur http://www-spi.lip6.fr/~mandel/rml.
                                    e
                              Quatri`me partie

          Applications et performances

9                                                          e
    Simulation de protocoles de routage dans les r´seaux mobiles ad                  hoc                   143
                    e                e      a
    9.1 Le routage g´ographique bas´ sur l’ˆge . . . . . . . . . . . . . . . . .     . . .   .   .   .   . 143
    9.2 Discussion du choix de ReactiveML pour implanter le simulateur .             . . .   .   .   .   . 144
    9.3 Description du simulateur . . . . . . . . . . . . . . . . . . . . . . . .    . . .   .   .   .   . 145
    9.4 Implantation en ReactiveML . . . . . . . . . . . . . . . . . . . . .         . . .   .   .   .   . 146
                                  e
        9.4.1 Structures de donn´es . . . . . . . . . . . . . . . . . . . . . .      . . .   .   .   .   . 146
        9.4.2 Comportement d’un nœud . . . . . . . . . . . . . . . . . . . .         . . .   .   .   .   . 147
    9.5 Analyse des performances du simulateur . . . . . . . . . . . . . . . .       . . .   .   .   .   . 152
    9.6 Extensions dynamiques . . . . . . . . . . . . . . . . . . . . . . . . .      . . .   .   .   .   . 153
    9.7 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .   . . .   .   .   .   . 154
                                     Chapitre 9

 Simulation de protocoles de routage
             e
   dans les r´seaux mobiles ad hoc

                                                       e e
    Une des principales applications que nous avons r´alis´es est un simulateur de protocoles
                      e                                  ee e e
de routage dans les r´seaux mobiles ad hoc. Ce travail a ´t´ r´alis´ en collaboration avec Farid
               e         e                                       e    e                 e
Benbadis de l’´quipe R´seaux et Performances du LIP6 et pr´sent´ dans [67]. Les r´sultats
         `                              ee e      e
obtenus a partir de ce simulateur ont ´t´ pr´sent´s dans [8, 7, 6].
                                   c
    Dans ce chapitre, nous commen¸ons par donner les principes des protocoles que nous voulons
                                                                        e
simuler. Ensuite, nous motivons l’utilisation de ReactiveML pour la r´alisation du simulateur.
                           e
Nous terminons avec la pr´sentation de l’implantation du simulateur et l’analyse de ses perfor-
mances.


9.1                 e              e       a
        Le routage g´ographique bas´ sur l’ˆge
          e                                  e e
    Les r´seaux mobiles ad hoc sont caract´ris´s par l’absence d’infrastructure physique. Dans
     e                      e c
ces r´seaux, les nœuds se d´pla¸ant et les connexions entre les nœuds changent dynamiquement.
                                 e                  e      `
De plus, des nœuds peuvent int´grer ou quitter le r´seau a tout moment.
         e                                                             e
    La d´couverte de la position de la destination est un des probl`mes principaux des proto-
                                    e       e e      e e
coles de routage classiques. Cette ´tape g´n`re en g´n´ral une surcharge importante de trafic.
             `           e                               e                 e     ˆ
Pour palier a ce probl`me, les protocoles de Routage G´ographique bas´ sur l’ Age (RGA) ont
ee               e                                        e
´t´ introduits r´cemment [47]. Ils ont pour avantage d’ˆtre relativement simples et efficaces.
                        e                  u
Contrairement aux m´thodes classiques o` la phase de localisation de la destination et la phase
                          e e                                  e
d’acheminement sont s´par´es, avec les protocoles RGA la d´couverte de la position de la des-
                     e                                                                 e e `
tination est effectu´e pendant l’acheminement des paquets. Il n’y a pas de phase d´di´e a la
localisation de la destination avant le transfert.
              e                                           e                          ˆ
    L’hypoth`se principale des protocoles de routage bas´s sur les positions et les ages est que
                   e      e        e                         e
chaque nœud est ´quip´ d’un syst`me de positionnement g´ographique (GPS ou autre). Ainsi,
tous les nœuds peuvent obtenir une information sur la position de chaque autre nœud. Cette
                       e                                             e `     ˆ           e
information est gard´e dans une table de positions et est associ´e a un age qui repr´sente le
       e     e                e        `                                                    e
temps ´coul´ depuis la derni`re mise a jour de la position. La table de positions est utilis´e lors
du routage d’un paquet pour estimer la position de la destination.
                e                                               ıt
    Avec ces m´thodes de routage, le nœud source ne connaˆ pas la localisation exacte de la
destination mais seulement une estimation. Cette estimation est mise dans le paquet et est affin´e e
                             e                                     e     a
pendant le routage. Nous pr´sentons l’algorithme de routage bas´ sur l’ˆge : EASE (Exponential
Age SEarch) [47]. Un nœud source n essaye de communiquer avec une destination d :

                                               143
144                                                e
                                 9. Simulation de r´seaux mobiles ad hoc



                                     pos(s,d)
                                                                           d
                                    a1
                                                                           pos(n2,d)

                           s              n1                       a2
                                                                    pos(n1,d)


                                    `
Fig. 9.1 – Routage d’un paquet de s a d : a1 et a2 sont des nœuds ancres qui affinent l’estimation
de la position de d.


 Set i := 0, age := ∞, a0 := s in
 While ai = d do
    chercher autour de ai un nœud ni tel que age(ni , d) age/2 ;
    age := age(ni , d);
    While le nœud n’est pas le nœud le plus proche de pos(ni , d) do
        acheminer vers pos(ni , d)
    done ;
    i := i + 1 ;
    ai := le nœud le plus proche de pos(ni , d)
 done

Les ai sont les nœuds ancres 1 , pos(n1 , n2 ) est l’estimation de la position de n2 donn´e par n1
                                                                                         e
                       a                                                                   e    e
et age(n1 , n2 ) est l’ˆge de cette information. Une illustration de cet algorithme est pr´sent´e
figure 9.1.
               e                                                                e
    L’efficacit´ des protocoles RGA repose sur la distribution des coordonn´es des nœuds. Dans
                                               e                 `
notre simulateur, nous comparons deux m´thodes de mise a jour des tables de positions. La
       e
premi`re, LE (pour Last Encounter), introduite dans [47], utilise les rencontres entre les nœuds.
Chaque nœud note dans sa table de positions la localisation et la date de tous les nœuds
                                  e
qu’il rencontre. La seconde m´thode, ELIP (Embedded Location Information Protocol) [8],
                                                                                 e
utilise les rencontres comme LE, mais utilise en plus les paquets de donn´es pour diss´minere
                             e                                                     e  e
les positions. Avec cette m´thode, un nœud source peut inclure ses coordonn´es g´ographiques
                                                                              `
dans les messages qu’il envoie. Ainsi, tous les nœuds qui participent a l’acheminement des
                           `
paquets peuvent mettre a jour leur table de positions avec cette information. Nous allons, avec
                                       e               e
le simulateur, comparer ces deux m´thodes de diss´mination.


9.2      Discussion du choix de ReactiveML pour implanter le si-
         mulateur
                          e                                e
   La simulation est une ´tape indispensable avant tout d´ploiement de nouveaux protocoles
                               e                                 e
de routage. Ceci est particuli`rement vrai dans le cadre des r´seaux mobiles ad hoc o` les u
   e        `        e              u                   `
exp´riences a grande ´chelle sont coˆteuses et difficiles a mettre en place. Les simulations nous
   1
    Les nœuds ancres cherchent une meilleure estimation de la position de la destination que celle incluse dans
le paquet.
                               9.3. Description du simulateur                                   145

                 e
permettent d’´valuer les protocoles en mesurant la diffusion des positions, la longueur des routes
                         e
ou la surcharge du r´seau en fonction du choix du protocole.
     Les outils de simulation standards comme NS-2 [79] ou OPNET [80] ne sont pas adapt´s a      e `
                               e                                              ee   c
la simulation de grands r´seaux mobiles ad hoc. NS-2 par exemple a ´t´ con¸u pour les r´seauxe
                                              e
filaires et traite donc assez mal les r´seaux sans fils. Par exemple, il semble inconcevable de
               e
simuler un r´seau de 1000 nœuds en NS-2. De plus en NS-2 comme en OPNET, la simulation de
                           e        e
la couche 3 (couche r´seau) n´cessite la simulation de la couche 2 (couche liaison). Ceci induit
       u       `     e                    e
un sˆrcout a l’ex´cution qui est ´vitable dans nos simulations. Le dernier point est que ces
                                 `
simulateurs sont difficiles a utiliser et demandent une longue phase d’apprentissage du fait de
leur richesse et leur complexit´.    e
                                      e ee                                                 e   e
     Une autre approche envisag´e a ´t´ l’utilisation de NAB [78]. Ce simulateur est d´velopp´ par
                                          e                c                               e
les auteurs de EASE. Il est donc sp´cialement con¸u pour les protocoles de routage g´ographique
     e     a                   e       e                      e                         e e
bas´ sur l’ˆge. NAB est d´velopp´ en Ocaml et est bas´ sur de la programmation ´v´nementielle.
                                                                    e
Nous verrons dans la section 9.5 que NAB n’est pas adapt´ pour les simulations avec un grand
                                                                            e
nombre de communications. La simulation de la couche liaison (mˆme sans perturbations) ra-
lentit les simulations.
                              e e                                       e           `
     Nous avons donc d´cid´ d’implanter un simulateur adapt´ exactement a notre probl`me.      e
             e       e             ee e e                    e
Une premi`re exp´rience a ´t´ r´alis´e en C. Pour d´velopper rapidement le simulateur, cette
                   ee               c       ıve.                e
implantation a ´t´ faite de fa¸on na¨ Le temps pass´ pour le calcul du voisinage des nœuds
                                                                                 e    `
dans ce simulateur rend difficile la simulation de topologies de taille sup´rieur a 200 nœuds. La
                                                                  e       `
seconde version du simulateur faite en ReactiveML a r´pondu a nos attentes. Elle permet de
simuler des topologies de plus de 1000 nœuds avec un grand nombre de communications.
     Les atouts de ReactiveML pour l’implantation du simulateur sont les suivants. La possibi-
   e     e                                               e
lit´ de d´finir facilement des structures de donn´es complexes comme en Ocaml aide beaucoup
     e                                             e                 e e
le d´veloppement. Le second point est l’ad´quation du mod`le r´actif de Boussinot au probl`me   e
`                                      e               e
a traiter. La composition parall`le avec une ´chelle de temps globale, les communications par
                       e            e                           `e
diffusion instantan´e et la cr´ation dynamique aident a ´crire simplement des algorithmes ef-
                                         e    e
ficaces. Il faut noter que le mod`le r´actif synchrone n’est pas contradictoire avec la nature
                    e                                        e     e          e
asynchrone des r´seaux. Le synchronisme garantit l’´quit´ dans l’ex´cution de tous les nœuds
comme on le ferait avec un langage imp´ratif.    e
                                                   ee
     On peut enfin remarquer qu’il aurait ´t´ difficile d’implanter le simulateur dans un langage
comme Lustre [51], Esterel [13] ou Signal [49] pour, au moins, deux raisons : l’utilisation
                            e                        e                    e
de structures de donn´es complexes partag´es entre les parties r´actives et combinatoires ainsi
          e                                                           e
que la cr´ation dynamique de processus qui n’est pas autoris´e dans ces langages.


9.3     Description du simulateur
                                                e              e                   e
   Le but du simulateur est de comparer deux m´thodes de diss´mination des coordonn´es :
                             e
LE et ELIP. Nous ne nous int´ressons pas aux performances du protocole de routage EASE,
     `                     e
mais a la comparaison des m´thodes de diffusion des informations de positions.

                  e                           `
Couches simul´es Un point important a noter est que nous ne simulons pas les couches
                             e
physique et liaison du mod`le OSI (les couches 1 et 2), mais uniquement la couche r´seau     e
                                                               e
(couche 3). Nous pouvons faire abstraction des deux premi`res couches car les protocoles que
     e                                e                 e
nous ´valuons sont des services utilis´s par la couche r´seau. Dans notre cas, la perte de paquets
             e                              e
ou les interf´rences n’influencent pas les r´sultats. Il est seulement important de comparer les
                          e                      e
deux algorithmes de diss´mination dans les mˆmes conditions.
146                                             e
                              9. Simulation de r´seaux mobiles ad hoc

                             e                                                       e
Topologie Le simulateur g`re des topologies rectangulaires. La topologie est d´coup´e en  e
grille. Les nœuds peuvent se placer sur les intersections de la grille. Plusieurs nœuds peuvent
             e
occuper le mˆme point. La distance entre deux points adjacents est de 1 m`tre.e

Voisinage Le voisinage d’un nœud est l’ensemble des nœuds avec lesquels il peut communiquer
                                                   e                           `
directement. Le rayon de couverture r d’un nœud d´finit la distance maximale a laquelle il peut
                                               `                 e       `
communiquer. Donc tous les nœuds qui sont a une distance inf´rieure a r d’un nœud n sont
                                                                                  e
les voisins de n. Dans le simulateur, nous supposons que tous les nœuds ont le mˆme rayon de
couverture.
               e                    e                   e           e
    Un param`tre de simulation int´ressant est la densit´. Elle repr´sente le nombre moyen de
                                                               e
voisins d’un nœud. Le rayon se calcule en fonction de la densit´ avec la formule suivante :

                                superficie totale de la topologie ∗ densit´
                                                                         e
                         r=
                                      nombre total de nœuds ∗ π

´                                                                          e
Echelle de temps Un instant de simulation correspond au temps n´cessaire pour qu’un ˆtre        e
                    e                       e                e
humain puisse se d´placer de quelques m`tres. En consid´rant qu’il faut quelques dizaines de
              `                                   `                                             e
millisecondes a un paquet pour aller de la source a la destination, il est raisonnable de consid´rer
                                                                                   a
que les nœuds sont statiques durant le transfert du paquet de la source jusqu’` la destination.
                                     e
Dans ce cadre, nous faisons l’hypoth`se que le routage est instantan´.   e

Algorithme de transfert de paquets Nous avons choisi d’implanter un algorithme de
            e                                               `
transfert tr`s simple. Un nœud transmet un paquet toujours a celui de ses voisins qui est le plus
proche de la destination. Si un paquet atteint une impasse (il faut repasser par le noeud qui
                                            e                      e
vient de transmettre le paquet), nous consid´rons que le routage a ´chou´e


9.4     Implantation en ReactiveML
           e                      e e                                                   c
    Nous d´crivons maintenant pr´cis´ment l’implantation du simulateur. Nous commen¸ons par
                                     e         e
la description des structures de donn´es utilis´es, puis nous verrons l’implantation d’un nœud.

9.4.1                      e
         Structures de donn´es
                                            e                e     a
    Pour utiliser un protocole de routage g´ographique bas´ sur l’ˆge, un nœud n doit connaˆ   ıtre
                                                    e                 `
sa position et avoir une table de positions. L’entr´e correspondant a un nœud a dans la table
                                                                               u
de position de n contient les champs suivants : [IDa , pos(n, a), date(n, a)] o` pos(n, a) est une
                                                                u         `
estimation de la position de a et date(n, a) indique l’instant o` n a mis a jour cette information
              e                        e e
pour la derni`re fois. Le nœud n poss`de ´galement la liste de ses voisins.
                                                    e
    On utilise donc un type enregistrement pour d´finir le type des nœuds :
type node =
  { id: int;
    mutable pos: position;
    mutable date: int;
    pos_tbl_le: Pos_tbl.t;
    pos_tbl_elip: Pos_tbl.t;
    mutable neighbors: node list; }
                            9.4. Implantation en ReactiveML                                   147

id est l’identificateur du nœud, pos est sa position courante et neighbors est la liste des nœuds
qui sont sous son rayon de couverture. Le champ date est un compteur local qui permet de
                                            ˆ
dater les informations et de calculer leur age. pos_tbl_le et pos_tbl_elip sont les tables de
                e                                       e
positions utilis´es pour simuler les protocoles de diss´mination LE et ELIP.
                                                      e                   e          e
     Les champs de l’enregistrement qui sont annot´s mutable peuvent ˆtre modifi´s, alors que
                   e              e
les autres sont fix´s lors de la cr´ation de l’enregistrement. Les tables de positions pos_tbl_le
                                                                     e             e
et pos_tbl_elip ne sont pas mutables, mais elles sont elles-mˆmes implant´es comme des
                e
structures imp´ratives dans le module Pos_tbl. Ces tables de positions associent une position
             `
et une date a chaque nœud.
                                                   e               e      a
     Les paquets pour les protocoles de routage g´ographique bas´ sur l’ˆge doivent contenir les
champs suivants : l’identificateur de la source et de la destination, une estimation de la position
                     a                                    e `
de la destination, l’ˆge de cette information et les donn´es a transmettre. Avec le protocole de
     e
diss´mination ELIP, le paquet peut en plus contenir la position du nœud source.
                                                                            e
     Dans le simulateur, les paquets n’ont pas besoin de contenir des donn´es mais en revanche,
ils contiennent des informations pour calculer des statiques. Ces informations sont aussi utiles
pour l’interface graphique.
type packet =
  { header: packet_header;
    src_id: int;
    dest_id: int;
    mutable dest_pos: position;
    mutable dest_pos_age: int;
    (* to compute statistics *)
    mutable route: node list;
    mutable anchors: node list; }
                                                        e
src_id, dest_id, dest_pos et dest_pos_age sont utilis´s pour le routage. route est la liste
                          e
des nœuds qui ont particip´ au routage et anchors la liste des nœuds ancres. header indique
si c’est un paquet LE ou ELIP.
type packet_header =
  | H_LE
  | H_ELIP of position option
                               e
Le type position option associ´ au constructeur H_ELIP indique que les paquets ELIP peuvent
contenir la position du nœud source ou pas.

9.4.2   Comportement d’un nœud
         e                                e            e                                 e
    L’ex´cution d’une simulation est l’ex´cution parall`le des nœuds qui composent le r´seau.
                                        `
Ainsi, le comportement d’un nœud est a la base du comportement du simulateur.
         e                             e           e                          e
    La r´action d’un nœud est compos´e de trois ´tapes. Un nœud (1) se d´place, (2) calcule
                                                                 e                 e
son voisinage et (3) participe au routage des paquets. Ces trois ´tapes sont combin´es dans un
                                     e e
processus node. Ce nœud est param´tr´ par pos_init (sa position initiale), une fonction move
                                                                                e
qui lui permet de calculer sa position suivante et une fonction make_msg qui cr´e une liste de
             `                                                       e
destinations a qui envoyer des paquets. La fonction make_msg repr´sente la couche transport
(couche 4).
148                                                 e
                                  9. Simulation de r´seaux mobiles ad hoc

let process node pos_init move make_msg =
  let self = make_node pos_init in
  loop
    self.date <- self.date + 1;

      (* Moving *)
      self.pos <- move self.pos;
      emit draw self;

      (* Neighborhood discovering *)
      ...
      update_pos_tbl self self.neighbors;

    (* Routing *)
    pause;
    let msg = make_msg self in
    ...
    pause;
  end
val node :
  int -> position -> (position -> position) -> (node -> int list) ->
  unit process
                 e                                             e          e
Ce processus cr´e un enregistrement de type node qui repr´sente son ´tat interne. Puis, il entre
                                                  e e
dans son comportement permanent qui est ex´cut´ sur trois instants. Au premier instant, le
             `                     e        e
nœud met a jour la date, se d´place et ´met sa nouvelle position sur un signal global draw
                                 `
pour l’interface graphique 2 . A la fin du premier instant et pendant le second, le voisinage est
       e                                      `
calcul´ et les tables de positions sont mises a jour en utilisant les rencontres entre les nœuds. Le
      e                        e                                 c          e
troisi`me instant est consacr´ au routage des paquets. En pla¸ant cette ´tape entre deux pause,
                                           e           e
on garantit que la topologie ne peut pas ˆtre modifi´e pendant le routage.

 e
D´placement
                                       e e
    Le mouvement des nœuds est param`tr´ par une fonction move. Cette fonction calcule la
                                        `
nouvelle position d’un nœud par rapport a sa position courante. La fonction move doit avoir la
signature suivante :
val move : position -> position
                                             e e                             e        e
   On peut implanter des fonctions de mobilit´ tr`s simples comme celle qui d´place al´atoirement
un nœud dans une des huit positions adjacentes.
let random pos = translate pos (Random.int 8)
val random : position -> position
                           `
(Random.int 8) est l’appel a la fonction int du module Random de la librairie standard de
Ocaml. La fonction translate retourne une nouvelle position.
                      e                   e              e      e
   On peut implanter ´galement des mod`les de mobilit´ plus r´alistes. Celui du Random
                               e                           e
Waypoint est un des plus utilis´s dans les simulations de r´seaux mobiles ad hoc. Dans ce
  2
                     e              e
      Des captures d’´cran sont donn´es figure 9.2.
                              9.4. Implantation en ReactiveML                                   149




       (a) Voisinage. Chaque segment vert           (b) Un exemple de routes en utilisant les
           e
       repr´sente une connection entre deux           e              e
                                                    m´thodes de diss´mination ELIP (bleu) et
                                   e
       voisins. Le cercle noir repr´sente la zone                                   e
                                                    LE (rouge). Le cercle rouge repr´sente la
       de couverture d’un nœud.                                     e
                                                    recherche effectu´e par un nœud ancre.


                                    e
              Fig. 9.2 – Captures d’´cran de l’interface graphique du simulateur.



     e                           e                                                     e
mod`le, un point est choisi al´atoirement dans l’espace de simulation et le nœud se d´place
       a
jusqu’` ce point. Quand le nœud atteint ce point, un nouveau point est choisi. Cette fonction
       e                                  e
est int´ressante, car elle doit garder un ´tat interne.
let random_waypoint pos_init =
  let waypoint = ref pos_init in
  fun pos ->
    if pos = !waypoint then waypoint := random_pos();
    (* move in the direction of !waypoint *)
    ...
val random_waypoint : position -> position -> position
                                                            e
L’application partielle de cette fonction avec un seul param`tre :
  random_waypoint (random_pos())
             e                                                            e
alloue la m´moire pour garder la destination et retourne une fonction de d´placement qui peut
e          e
ˆtre utilis´e comme argument par un nœud.


Calcul du voisinage

                e      e                          e                            ee
    Dans des r´seaux r´els, le voisinage est donn´ directement par les propri´t´s physiques
     e                                               e          e                           e
du r´seau. Au contraire, dans un simulateur, il doit ˆtre calcul´. De plus, un des points cl´s
            e                         e                                           c
de l’efficacit´ du simulateur est cette ´tape de calcul du voisinage. Nous commen¸ons ici par
              e                                                             e
donner une m´thode simple pour ce calcul, puis nous verrons comment l’am´liorer.
                                                    ıtre
    Pour calculer son voisinage, un nœud doit connaˆ les positions des autres nœuds. Dans
           e      e                                                                e
cette premi`re m´thode, nous utilisons un signal hello pour collecter les coordonn´es de tous
150                                             e
                              9. Simulation de r´seaux mobiles ad hoc




                                                     c
                                                 n

                                                         b
                                             a




                        e     e        e                e                       e      e
Fig. 9.3 – Topologie d´coup´e en carr´s. Le nœud n ´met sa position sur les carr´s gris´s et
e                           e
´coute seulement sur le carr´ dans lequel il se trouve.


                        e                                                           e
les nœuds. Chaque nœud ´met sa position sur hello qui collecte toutes les valeurs ´mises. Ainsi,
                                                                         e
le code d’un nœud pour le calcul du voisinage est le suivant (self est l’´tat interne du nœud) :
   emit hello self;
   await hello(all) in
   self.node_neighbors <- get_neighbors self all;
                                                                            `
La fonction get_neighbors retourne la sous liste de all contenant les nœuds a une distance
   e
inf´rieure au rayon de couverture (coverage_range) de self.
let get_neighbors n1 others =
  let filter n2 =
    distance n1.pos n2.pos < coverage_range
  in
  List.filter filter others
val get_neighbors : node -> node list -> node list
              e                                                                          e
     Cette m´thode pour le calcul du voisinage est simple, mais a pour inconv´nient d’ˆtre      e
   u                                                                        `
coˆteuse. En effet, chaque nœud doit calculer sa distance par rapport a tous les autres nœuds
              `                        e               e                                   e
participant a la simulation. Pour am´liorer cette m´thode, l’espace de simulation est d´coup´ ene
                                         e`
zones. Un signal hello est alors associ´ a chaque zone. Ainsi, un nœud doit calculer sa distance,
uniquement, avec les nœuds se trouvant dans les zones qui sont sous son rayon de couverture.
            e                                                    e
     Consid´rons le nœud n de la figure 9.3. D’une part, n ´met sa position sur les signaux
       e                   e                          e          e      e
associ´s aux quatre carr´s qui sont sous sa port´e (les carr´s gris´s dans la figure). D’autre
                                                                              e        e
part, les nœuds a et c qui ont leur rayon de couverture qui touche le carr´ de n, ´mettent leurs
                               e`          e    e                        e
positions sur le signal associ´ a ce carr´. n ´coute le signal du carr´ sur lequel il se trouve, il
   c                                 `
re¸oit donc les positions de a et c. A partir de ces informations, n calcule sa distance par rapport
`                                                                                    e
a a et c. Il en conclue que c est son voisin alors que a ne l’est pas. n ne consid`re pas le nœud
          e                                          e        e
b car b n’´met pas sa position sur le signal associ´ au carr´ sur lequel n se trouve.
                                         e                    `
     Tous les signaux hello sont stock´s dans un tableau a deux dimensions hello_array. On
  e
d´finit la fonction get_areas qui retourne la zone sur laquelle le nœud se trouve et la liste des
zones voisines qui sont sous son rayon de couverture.
val get_areas : position -> (int * int) * (int * int) list
                                                   e
   Maintenant, le comportement d’un nœud est d’´mettre sa position dans toutes les zones qui
                 e                                         `                        e
sont sous sa port´e et de calculer sa distance par rapport a tous les nœuds qui ont ´mis leurs
                                                   9.4. Implantation en ReactiveML                                                                                          151


                          3.5                                                                    0.14
                                                             area = 2*range                                                                             D = 10
                                                                area = 1000                                                                             D = 20
                           3                                                                                                                            D = 30
                                                                                                 0.12

                          2.5
                                                                                                  0.1
                           2
               time (s)




                                                                                      time (s)
                                                                                                 0.08
                          1.5

                                                                                                 0.06
                           1

                                                                                                 0.04
                          0.5

                           0                                                                     0.02
                                0    1000   2000    3000         4000   5000   6000                     0   100   200   300   400   500     600   700    800     900 1000
                                               number of nodes                                                                  area size




                      (a) Comparaison du temps de si-                                        (b) Comparaison du temps de simu-
                      mulation en fonction du nombre                                         lation en fonction de la taille des
                                               e
                      de nœuds et de la m´thode de                                                           e        e e
                                                                                             zones pour la m´thode am´lior´e.
                       e
                      d´couverte du voisinage.


                                    Fig. 9.4 – Temps de simulation pour le calcul du voisinage.



positions sur sa zone. Donc, le code d’un nœud devient le suivant :
   let (i,j) as local_area, neighbor_areas =
     get_areas self.pos.x self.pos.y
   in
   List.iter
     (fun (i,j) -> emit hello_array.(i).(j) self)
     (local_area::neighbor_areas);
   await hello_array.(i).(j) (all) in
   self.neighbors <- get_neighbors self all;
                                                                              e
    La figure 9.4 montre l’effet de cette optimisation sur le temps d’ex´cution. Dans la fi-
                                          e    e         u                  e
gure 9.4(a), nous comparons la premi`re m´thode, o` tous les nœuds ´mettent et ´coutent    e
          e                                e                           e
sur le mˆme signal, avec la seconde m´thode que l’on vient de pr´senter. Dans la premi`re        e
  e                                                            `
m´thode, chaque nœud doit calculer sa distance par rapport a tous les autres nœuds. Le temps
                                                                  e        u
de calcul est ainsi beaucoup plus long que dans la seconde m´thode o` un nœud calcule sa
distance seulement avec les nœuds qui sont dans les zones adjacentes. On observe que pour
                             e                                        e
1000 nœuds, la seconde m´thode est 2 fois plus rapide que la premi`re. Pour 2000 nœuds, elle
est 4 fois plus rapide et pour 5000 nœuds elle est plus de 20 fois plus rapide.
                                                               e
    Dans la figure 9.4(b), on se concentre sur la seconde m´thode. Cette figure repr´sente lee
         e
temps n´cessaire pour simuler 2000 nœuds sur une topologie de taille 1000 en utilisant trois
densit´s diff´rentes 3 et en faisant varier la taille des zones. Comme nous pouvons l’observer,
       e     e
                      e
le temps de calcul d´pend fortement de la taille des zones. Diviser la topologie en un nombre
                           e
important de petits carr´s n’est pas efficace. Dans ce cas, chaque nœud passe son temps a            `
e                                                                     e
´mettre sa position sur un nombre trop important de signaux. De mˆme, diviser la topologie en
                e      e                                            c
de grands carr´s est ´galement peu efficace. Ici, chaque nœud re¸oit un nombre important de
position et doit calculer sa distance avec des nœuds qui sont tr`s ´loign´s de lui 4 . Les r´sultats
                                                                 e e     e                   e
                                        e        ee     `
de simulations montrent que des carr´s de cot´ ´gal a 2 fois le rayon de couverture semblent
  3
                                 e     e
      On rappelle que la densit´ repr´sente le nombre moyen de nœuds par zone de couverture.
  4
              u                          e     `                                      `         e    e
      Le cas o` la taille de la zone est ´gale a la taille de la topologie correspond a la premi`re m´thode.
152                                                                     e
                                                      9. Simulation de r´seaux mobiles ad hoc


                       5                                                                                 1.6e+08
                                                                    D = 20                                                                               D = 20
                      4.5
                                                                                                         1.4e+08
                       4
                                                                                                         1.2e+08
                      3.5




                                                                                        Memory (words)
                                                                                                          1e+08
                       3
           time (s)




                      2.5                                                                                 8e+07

                       2
                                                                                                          6e+07
                      1.5
                                                                                                          4e+07
                       1
                                                                                                          2e+07
                      0.5

                       0                                                                                      0
                            0    500   1000   1500   2000   2500   3000   3500   4000                              0   500   1000   1500   2000   2500   3000   3500   4000
                                               number of nodes                                                                       number of nodes




                                (a) Temps de simulation.                                                                      e
                                                                                                              (b) Occupation m´moire.


                               e                                          e
       Fig. 9.5 – Simulations d´pendant du nombre de nœuds avec une densit´ D=20.



e
ˆtre un bon compromis.

Routage
              e e                                                                ee e
    La derni`re ´tape est le routage des paquets. L’algorithme de routage a ´t´ d´crit dans la
                                                                                     e
section 9.1. Le point important est que nous supposons que le routage est instantan´. Ceci signifie
                               e               e                                    e       e
que les connexions dans le r´seau sont fig´es pendant le routage. Cette hypoth`se est r´aliste
                                            e       `
car nous supposons que les nœuds se d´placent a vitesse humaine alors que les paquets sont
           `                                             e                  `     e
transmis a la vitesse des ondes radio. La topologie du r´seau change donc a une ´chelle de temps
                 `
correspondant a la seconde alors que les paquets mettent quelques dizaines de millisecondes pour
                   `                         e                     e
aller de la source a la destination. La cons´quence de cette hypoth`se est que l’on peut implanter
la fonction de routage avec une fonction Ocaml qui est instantan´e.  e
                                     e             e                      e
    Dans le simulateur, les deux m´thodes de diss´mination de coordonn´es que nous comparons
               e
utilisent le mˆme algorithme de transfert de paquets. Un paquet est toujours transmis au voisin
le plus proche (en distance Euclidienne) de la destination. Du point de vue de l’implantation,
             e                                                           e    ` e
le point int´ressant de la fonction forward est qu’un nœud peut acc´der a l’´tat interne des
                        e                 e
autres nœuds qui s’ex´cutent en parall`le. ReactiveML garantit que les actions combinatoires
                           e           e         e                 `e         e e
sont atomiques. Les acc`s aux donn´es partag´es n’ont donc pas a ˆtre prot´g´s comme dans le
     e                   e
mod`le des threads pr´emptifs standards.


9.5     Analyse des performances du simulateur
                              e                          e
    Le temps de simulation d´pend de nombreux param`tres : nombre de nœuds, rayon de cou-
                             e                                                            e
verture, nombre de paquets ´mis, taille de la topologie, etc. Pour faire des simulations r´alistes,
                     e                  e     e              e
nous lions ces param`tres par la densit´ du r´seau qui repr´sente le nombre de nœuds par zone
de couverture.
                  c
    Nous commen¸ons par mesurer les limites de notre simulateur. La figure 9.5(a) repr´sente e
                                                                    e
le temps de simulation en fonction du nombre de nœuds dans le r´seau en gardant une densit´       e
                           a
constante. On observe qu’` partir de 3300 nœuds environ, le temps de calcul devient subitement
                                          u `                  e
beaucoup plus important. Ce saut est dˆ a l’occupation m´moire. Une fois la limite de 3300
         e    e                                                  e
nœuds d´pass´e, il n’y a plus suffisamment d’espace dans la m´moire vive et le programme doit
          e                            e                       e
faire des ´changes avec le disque. Les ´changes disques font ´crouler les performances. On peut
                                                          9.6. Extensions dynamiques                                                                                 153


                      12                                                                           450
                                                               RML, D = 20                                                                   RML, D = 20
                                                               NAB, D = 20                                                                   NAB, D = 20
                                                                                                   400
                      10
                                                                                                   350

                      8                                                                            300




                                                                                       time (ms)
                                                                                                   250
           time (s)




                      6
                                                                                                   200

                      4                                                                            150

                                                                                                   100
                      2
                                                                                                    50

                      0                                                                              0
                           0   500   1000   1500   2000   2500    3000   3500   4000                     0   500   1000   1500   2000   2500    3000   3500   4000
                                             number of nodes                                                               number of nodes




                                    e
                           (a) avec ´mission de paquets.                                                      e
                                                                                                     (b) sans ´mission de paquets.


Fig. 9.6 – Comparaison des temps de simulation entre NAB et le simulateur ReactiveML.
                 e                                          e
Les simulations d´pendent du nombre de nœuds avec une densit´ D=20.



                                            e                e
voir dans la figure 9.5(b) l’occupation m´moire pour les mˆmes simulations. La consommation
  e
m´moire est au moins quadratique car chaque nœud a une table de positions contenant des
                                                 e
informations sur tous les autres nœuds. Pour d´passer cette limitation, nous pouvons utiliser la
  e                                                                         `
mˆme technique que dans le simulateur NAB. Cette technique consiste a limiter le nombre de
                                                      `        ıtre
nœuds destinations pour que seul ces nœuds aient a apparaˆ dans les tables de positions.
                                                                                  e       e
    Nous comparons maintenant notre simulateur avec NAB [78], le simulateur d´velopp´ par les
                                                           e                             u
auteurs de EASE. La figure 9.6(a) montre le temps d’ex´cution pour une simulation o` chaque
       e                 `
nœud ´met un paquet a chaque instant. Ce type de simulation avec beaucoup de mobilit´ et      e
                             e               e                            e
de communications est int´ressant pour ´valuer les protocoles de diss´mination. Les courbes
                                                                        e e
montrent que l’implantation en NAB est moins efficace que celle r´alis´e en ReactiveML.
                                     e
Mais cette comparaison n’est pas ´quitable ! En effet, NAB simule la couche liaison alors que
                                                 e
le simulateur ReactiveML ne le fait pas. Mˆme si on choisit une couche liaison parfaite, la
                                              u
simulation de la couche liaison induit un sˆrcout pour le routage de tous les paquets.
                        e
    Afin de comparer ´quitablement les implantations NAB et ReactiveML, figure 9.6(b),
                                                      e
nous les comparons en faisant des simulations sans ´mission de paquets. Ainsi, nous comparons
                          e
seulement le temps de d´couverte du voisinage. Dans ces simulations, la couche liaison n’inter-
                                                                  e               e
vient pas. Les deux implantations font donc exactement la mˆme chose. Ces r´sultats restent
   e               e           e                          e
int´ressants car l’´tape de d´couverte du voisinage repr´sente environ 25% du temps global de
                                                  e
simulation lorsque l’on utilise la version optimis´e du simulateur. Les courbes de la figure 9.6(b)
nous montrent que l’implantation ReactiveML est environ deux fois plus rapide que NAB sur
ces simulations.
                                           e
    Le dernier point que nous avons test´ est la robustesse de l’implantation. Nous avons laiss´ e
                     e
une simulation s’ex´cuter pendant 20 jours. Nous pouvons voir dans la figure 9.7(a) que l’occu-
         e                e
pation m´moire est rest´e constante pendant cette longue simulation.


9.6    Extensions dynamiques
              e                                               e
   Dans les r´seaux mobiles ad hoc, les protocoles doivent ˆtre robustes aux changements de
                                                                 e         e
topologies. En particulier, ils doivent prendre en compte l’arriv´e et le d´part de nœuds. Donc,
                                  e
notre simulateur doit pouvoir g´rer l’ajout et la suppression de nœuds en cours de simulation.
154                                                                      e
                                                       9. Simulation de r´seaux mobiles ad hoc


                               2e+07                                                                     1e+08
                                                                     heap words                                                                   heap words
                                                                      live words                         9e+07                                     live words

                                                                                                         8e+07
                              1.5e+07
                                                                                                         7e+07
             Memory (words)




                                                                                        Memory (words)
                                                                                                         6e+07

                               1e+07                                                                     5e+07

                                                                                                         4e+07

                                                                                                         3e+07
                               5e+06
                                                                                                         2e+07

                                                                                                         1e+07

                                   0                                                                         0
                                        0     500000         1e+06            1.5e+06                            0   1000   2000      3000      4000      5000   6000
                                                       Time (s)                                                             Time (number of instants)




                                         e
                         (a) Occupation m´moire pendant 20                                                            e
                                                                                                    (b) Occupation m´moire pour une
                         jours.                                                                                 u                    e
                                                                                                    simulation o` un nœud est supprim´
                                                                                                    `
                                                                                                    a chaque instant.


                                                                   e
                                            Fig. 9.7 – Occupation m´moire en fonction du temps


                e              e            e
      Un nœud pr´emptible est d´fini par l’ex´cution d’un nœud dans une construction do/until :
let process preemptible_node pos_init move make_msg kill =
  do
    run (node pos_init move make_msg)
  until kill done
                                                          e                           u
    Dans la figure 9.7(b), nous observons l’occupation m´moire pour une simulation o` un nœud
             e`
est supprim´ a chaque instant. Cela montre que le glaneur de cellules fonctionne aussi sur les
processus.
                                   e                                     e e      a `
    Nous voyons maintenant la cr´ation dynamique de nœuds. Elle est r´alis´e grˆce a la compo-
             e          e               e                                e
sition parall`le et la r´cursion. Nous d´finissons le processus add qui cr´e un nouveau processus
`                                          e
a chaque fois que le signal new_node est ´mis :
let rec process add new_node start =
  await new_node (pos) in
  run (add new_node start)
  ||
  await immediate start;
  run (node pos
           (random_waypoint (random_pos()))
           make_msg)
                        e e
Ce processus est param´tr´ par deux signaux : new_node et start. Le signal new_node est
e                                                              e      ee                 e
´mis (avec une position initiale) lorsqu’un nouveau nœud doit ˆtre cr´´. start est utilis´ pour
                                                               e    `                 e
synchroniser les nouveaux nœuds avec les autres. Ce signal est ´mis a chaque nouvelle ´tape de
  e
d´placement.


9.7       Conclusion
                          e
    L’implantation compl`te du simulateur (avec l’interface graphique et la sortie des statis-
            e                                                       e
tiques) repr´sente environ 1200 lignes de ReactiveML. L’expressivit´ du langage nous a per-
       e                                                               e
mis d’´crire assez simplement un simulateur suffisamment efficace pour r´aliser les simulations
                                      9.7. Conclusion                                        155

             e                          e            ee       e
qui nous int´ressent. Le simulateur a ´galement ´t´ adapt´ pour tester les performances des
   e            e
diff´rentes am´liorations de ELIP ([7, 6]).
              e          e                                                e
    Cette exp´rience de r´alisation d’un simulateur de protocoles pour r´seaux mobiles ad hoc
                  `                                                            e
ne cherche pas a concurrencer des simulateurs comme NS-2 ou OPNET. L’id´e est de proposer
                                                     e e
une alternative aux langages de programmation g´n´ralistes afin de faciliter l’implantation de
               e e `           e
simulateurs d´di´s a des probl`mes non standards.
                            e          e                                           e e
    Les foncteurs ont manqu´ lors du d´veloppement. En particulier, nous avons r´alis´ plusieurs
implantations des tables de positions et l’utilisation de foncteurs permettrait d’en changer sim-
plement.


 e   e
R´sum´
                  e                         e                              e
    Nous avons d´crit dans ce chapitre la r´alisation d’un simulateur de r´seaux mobiles ad hoc.
              e                        e                                              e
    La premi`re partie du chapitre pr´sente le principe des protocoles de routage g´ographique
    e       a               e
bas´ sur l’ˆge dans les r´seaux mobiles ad hoc. Ces protocoles utilisent une estimation de la
                                                                                    e
position de la destination pour le routage des paquets. Cette estimation est affin´e pendant le
                                                                                  e
routage. Pour utiliser cette famille d’algorithmes de routages, les nœuds poss`dent une table
                         `                               e                             e
de positions associant a chaque nœud une position g´ographique. Nous avons pr´sent´ deux   e
  e               e                       `        `
m´thodes de diss´mination qui servent a mettre a jour ces tables de positions. Le simulateur a
ee e e                                 e
´t´ r´alis´ pour comparer ces deux m´thodes.
                                 e                         e
    Ensuite, nous avons montr´ que les simulateurs de r´seaux classiques comme NS-2 ou OP-
                          e                   e                                 e e
NET ne sont pas adapt´s pour notre probl`me. C’est pourquoi nous avons d´cid´ d’implanter
                           e e`                                     e                      e
un nouveau simulateur d´di´ a la simulation des protocoles de diss´mination de coordonn´es. Le
                                e                                                    e
choix de ReactiveML pour r´aliser cette implantation se justifie par l’expressivit´ du langage
                         e     e                             e                                 e
algorithmique, la facilit´ de d´finir des structures de donn´es complexes et le fait que le mod`le
 e                              e                                            e
r´actif de Boussinot est adapt´ pour la programmation de ce type de syst`mes. En effet, nous
                     e                                                               e
retrouvons du parall´lisme, de nombreuses synchronisations et communications et ´galement de
      e
la cr´ation dynamique de processus.
                         e                                             e
    Enfin, nous avons d´crit le simulateur, son implantation et analys´ ses performances. Ce qui
                    e                   ee
ressort de cette exp´rience est qu’il a ´t´ assez simple d’implanter un simulateur suffisamment
                e                                        e              e
efficace pour r´aliser nos simulations. Nous avons illustr´ ce point en pr´sentant une optimisation
simple permettant de calculer le voisinage d’un nœud.
                                    e
                              Cinqui`me partie

                Discussions et conclusion

10 Discussions                                                                                                                                       159
                                e
   10.1 Les compositions parall`les . . . . . . . . . . . . . . . . .                              .   .   .   .   .   .   .   .   .   .   .   .   . 159
                     e           e
        10.1.1 Parall`le imbriqu´ . . . . . . . . . . . . . . . . . .                              .   .   .   .   .   .   .   .   .   .   .   .   . 159
                     e
        10.1.2 Parall`le associatif et commutatif . . . . . . . . . .                              .   .   .   .   .   .   .   .   .   .   .   .   . 160
               e
   10.2 Les pr´emptions . . . . . . . . . . . . . . . . . . . . . . .                              .   .   .   .   .   .   .   .   .   .   .   .   . 161
                               e
        10.2.1 Le choix de la s´mantique du do/until . . . . . .                                   .   .   .   .   .   .   .   .   .   .   .   .   . 161
        10.2.2 Les exceptions . . . . . . . . . . . . . . . . . . . .                              .   .   .   .   .   .   .   .   .   .   .   .   . 162
   10.3 Les signaux . . . . . . . . . . . . . . . . . . . . . . . . . .                            .   .   .   .   .   .   .   .   .   .   .   .   . 164
        10.3.1 Liaison des noms de signaux . . . . . . . . . . . .                                 .   .   .   .   .   .   .   .   .   .   .   .   . 164
                                                           e
        10.3.2 Les signaux comme des valeurs de premi`re classe                                    .   .   .   .   .   .   .   .   .   .   .   .   . 165
                         e
        10.3.3 La multi-´mission . . . . . . . . . . . . . . . . . . .                             .   .   .   .   .   .   .   .   .   .   .   .   . 166
                 e
        10.3.4 S´mantique du pre . . . . . . . . . . . . . . . . . .                               .   .   .   .   .   .   .   .   .   .   .   .   . 166
        10.3.5 Les await . . . . . . . . . . . . . . . . . . . . . . .                             .   .   .   .   .   .   .   .   .   .   .   .   . 168
         e                   e e
   10.4 S´paration instantan´/r´actif . . . . . . . . . . . . . . . .                              .   .   .   .   .   .   .   .   .   .   .   .   . 168
        10.4.1 Le statut de signal/in et emit . . . . . . . . . .                                  .   .   .   .   .   .   .   .   .   .   .   .   . 168
        10.4.2 Processus avec une valeur de retour . . . . . . . .                                 .   .   .   .   .   .   .   .   .   .   .   .   . 169
                   e                                 e
        10.4.3 Ex´cution du programme et code r´entrant . . . .                                    .   .   .   .   .   .   .   .   .   .   .   .   . 170

11 Extensions                                                                                                                                        173
                     e
   11.1 Les scripts r´actifs . . . . . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   . 173
   11.2 Interface avec d’autres langages . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   . 176
                        e e
   11.3 Configurations ´v´nementielles . . .        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   . 178
   11.4 Filtrage de la valeur des signaux . .      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   . 179
                               e e
   11.5 La composition parall`le s´quentielle      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   . 182
   11.6 Automates . . . . . . . . . . . . . .      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   . 183

12 Conclusion                                                                                                                                          185
         e     e
   12.1 R´sum´ . . . . . . . . . . . . . . .     . . . . . . .             .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   185
   12.2 Perspectives . . . . . . . . . . . . .   . . . . . . .             .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   188
        12.2.1 La composition asynchrone         . . . . . . .             .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   188
        12.2.2 Programmation de syst`mes e       embarqu´s e               .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   188
                 e
        12.2.3 V´rification formelle . . . .      . . . . . . .             .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   189
                                   Chapitre 10

                                  Discussions

                                     e
     Dans cette partie, nous nous int´ressons aux choix faits dans le design du langage et aux
extensions que nous pourrions apporter. Dans le premier chapitre, nous comparons les construc-
                                     `                                         e e
tions de ReactiveML par rapport a celles des autres implantations du mod`le r´actif et nous
   e                       e                                   e                      e
pr´sentons d’autres choix s´mantiques que nous avons envisag´s. Le second chapitre pr´sente les
                                                                                         e
nouvelles extensions du langage incluses dans la distribution et que nous n’avons pas d´crites
                     e e               e        e
dans les chapitres pr´c´dents. Nous pr´sentons ´galement quelques extensions possibles.
                                                          e                         e
     Le langage est encore jeune. Les choix que nous pr´sentons ici ne sont pas d´finitifs. Ils
                        e
s’appuient sur nos exp´riences de programmation en ReactiveML, sur la formalisation du
                                                             e
langage et sur son implantation. Ces aspects nous ont guid´s pour trouver un compromis pour
                                         `
que les constructions du langage soient a la fois utiles, simples et que leur implantation reste
efficace.


10.1                            e
         Les compositions parall`les
10.1.1          e          e
          Parall`le imbriqu´
    Des langages comme Loft et ULM proposent un seul niveau de composition parall`le           e
                      e
comme dans le mod`le des threads. Au contraire, dans SL, Junior ou ReactiveML, nous
                                                e `       e                               e
avons le droit d’utiliser la composition parall`le a l’int´rieur d’un bloc. C’est un des h´ritages
de Esterel.
                               e             e e
    La seconde forme de parall`le est caract´ris´e par la synchronisation de la terminaison de ses
                                   e                                     e
branches. Ainsi, il est possible d’´crire simplement le programme qui ´met le signal finished
                                  e e             e              e        e
lorsque deux processus p et q ex´cut´s en parall`le ont termin´ leur ex´cution.

  (run p || run q); emit finished

    `
    A l’usage, nous trouvons plus simple de pouvoir composer directement deux expressions
    o
plutˆt que d’utiliser les primitives create de Loft ou thread de ULM. Ces primitives im-
          `            e                                           e
plantent a la fois l’ex´cution d’un processus et sa mise en parall`le. En ReactiveML, le run
                                                        e                                e
se comporte comme l’application de fonction, il n’ex´cute pas le processus en parall`le avec
                                                                                     ` e
l’appelant. Il est toujours possible de remplacer les run par le corps des processus a ex´cuter :
                                        e    e
le principe de substitution est ainsi pr´serv´.

                                               159
160                                        10. Discussions

10.1.2          e
          Parall`le associatif et commutatif
                e                           e            e e                                 e
    Une des diff´rences entre les calculs bas´s sur le mod`le r´actif vient de la commutativit´ du
      e                                                                   e
parall`le. En ReactiveML comme en Junior, la composition parall`le est commutative. Par
                                     e                                 e
contre, dans les SugarCubes, l’op´rateur merge de mise en parall`le garantit que la branche
                          e
gauche est toujours activ´e avant la branche droite. Pour Loft, les deux modes d’ex´cutione
sont possibles.
                       e                e                               e
    Nous avons souhait´ conserver l’op´rateur de composition parall`le commutatif pour deux
                            e             e                                    e
raisons : le compositionalit´ et l’efficacit´. Ce n’est pas parce que le parall`le est de gauche a`
                                                e
droite que l’ordonnancement est toujours le mˆme. Illustrons cela sur la cascade inverse :
  let process p s1 s2 s3 =
    await immediate s3; print_int 3
    ||
    await immediate s2; print_int 2;
    emit s3
    ||
    await immediate s1; print_int 1;
    emit s2
    ||
    emit s1
  val p :
  (unit, ’a) event -> (unit, ’b) event -> (unit, ’c) event -> unit process
        e                                              e
Nous ex´cutons ce processus dans trois conditions diff´rentes. Au premier instant le processus p
      e e                 e                    e e            e          e              `
est ex´cut´ seul, au deuxi`me instant il est ex´cut´ en parall`le avec l’´mission de s2 a sa droite
            e                  e               `
et au troisi`me instant avec l’´mission de s2 a sa gauche :
  let process main =
    signal s1, s2, s3 in
    print_string "Instant 1 : "; run (p s1 s2 s3); pause;
    print_string "\nInstant 2 : "; (run (p s1 s2 s3) || emit s2); pause;
    print_string "\nInstant 3 : "; (emit s2 || run (p s1 s2 s3))
  val main : unit process
                                 `                       e
Avec un ordonnancement de gauche a droite, la sortie affich´e par ce processus est la suivante :
  Instant 1 : 123
  Instant 2 : 213
  Instant 3 : 231
                                          e              e
Nous observons trois ordonnancements diff´rents pour l’ex´cution de p alors que l’environnement
                     e   `
des signaux est le mˆme a chaque instant. La composition de p avec d’autres processus change
                   `     e                                                              e
l’ordonnancement a l’int´rieur de p. Il est donc dangereux de se baser sur la priorit´ de la
branche gauche pour construire les programmes.
                                                                                   e
    Nous proposons dans le chapitre 11.5 une construction |> de composition parall`le de gauche
`                                                                         u
a droite. Cette construction est une version moins expressive de merge o` la branche gauche
               e
ne peut pas d´pendre de la branche droite. Ainsi l’ordonnancement ne peut pas changer en
fonction du contexte.
    Il faut remarquer que l’ordonnancement a de l’impact uniquement sur les programmes a      `
                                                   e                                   ee
effets de bord. Nous avons vu chapitre 3.4 que la s´mantique de ReactiveML sans r´f´rences
                                               e
                                   10.2. Les pr´emptions                                       161

      e                    e                e                      e                  e
est d´terministe. Par cons´quent, si les op´rations faites sur la m´moire dans les diff´rentes
               e                                                          e
branches parall`les sont associatives et commutatives, le programme est d´terministe quelque
soit l’ordonnancement. Par exemple le programme suivant affiche toujours 2 :
  let x = ref 0 in
  (x := !x + 1 || x := !x + 1); print_int !x
            ee                        e  e                                          e
Les propri´t´s importantes du mod`le r´actif sont d’une part de garantir que l’ex´cution des
                       e                            e              e                   u
expressions instantan´es est atomique. Ainsi nous ´vitons les probl`mes des threads o` il faut
  e                                                       e            e
d´finir des sections critiques pour pouvoir modifier de la m´moire partag´e. D’autre part, d’avoir
                    e                                            e
une implantation d´terministe afin de pouvoir reproduire une ex´cution.
                                                 e
    Remarquons enfin que la composition parall`le associative et commutative est plus facile
`                                            e                 e             e            e
a implanter efficacement. L’ordre des parall`les ne doit pas n´cessairement ˆtre conserv´. De
          e                         `
plus, la s´mantique reste ouverte a l’implantation de nouvelles techniques d’ordonnancement
plus efficaces.


10.2           e
         Les pr´emptions
10.2.1                    e
          Le choix de la s´mantique du do/until
              e   e                     e                       e
     Le mod`le r´actif propose deux s´mantiques pour la pr´emption. Celle de la construction
kill de SL [24] et celle du do/until de Junior [56].
           e                                            e
     La pr´emption de ReactiveML a repris la s´mantique du kill. C’est une pr´emption      e
                        e e`               u                e            e                     e
faible : le corps est ex´cut´ a l’instant o` le signal de pr´emption est ´mis. La particularit´ de
                                                    e             `                       e
cette construction est d’effectuer le traitement d’´chappement a l’instant suivant la pr´emption.
                                                        e                         e
     La construction do/until de Junior a une s´mantique plus fine. Elle d´finit ´galement  e
        e                                    e                         e
une pr´emption faible, mais en cas de pr´emption, le traitement d’´chappement peut ˆtre ef-  e
      e           e                e`                 e                     e
fectu´ instantan´ment ou report´ a l’instant d’apr`s. Son comportement d´pend de l’expression
            e     e                     ee
qui est pr´empt´e. Si le corps est arrˆt´ uniquement sur des instructions pause, le traitement
   e                          e                                     e
d’´chappement est instantan´. Au contraire, si le corps test la pr´sence d’un signal, le traitement
   e                       e                   e              e              e
d’´chappement est retard´ d’un instant pour ´viter les probl`mes de causalit´. Par exemple, dans
                                             e                         e
l’expression de gauche, le traitement de l’´chappement est instantan´ et dans celle de droite, il
            e`                        e                                         e
est effectu´ a l’instant suivant la pr´emption pour ne pas contredire l’hypoth`se s’ est absent :

         do                                                do
           loop pause end                                    loop await s’ end
         until s(x) -> emit s’ done                        until s(x) -> emit s’ done

        e
   La s´mantique du do/until de Junior est plus expressive. Elle permet par exemple de
 e                                                                  e
d´finir le processus await_immediate_or qui attend que s1 ou s2 soit ´mis :
  let process await_immediate_or s1 s2 =
    do do
      loop pause end
    until s1 done until s2 done
  val await_immediate_or : (’a, ’b) event -> (’c, ’d) event -> unit process
         e                     e                   e
Avec la s´mantique de Junior, d`s que s1 ou s2 est ´mis, le processus termine. Alors qu’en
                       e
ReactiveML (avec la s´mantique de SL), ce processus a le comportement d’un await non
    e
imm´diat.
162                                        10. Discussions

Remarque :
                                                e e
   Nous verrons chapitre 11.3 les configurations ´v´nementielles en ReactiveML. Elles per-
             e
   mettent d’´crire le programme suivant :
       let process await_immediate_or s1 s2 =
         await immediate (s1 \/ s2)
       val await_immediate_or : (’a, ’b) event -> (’c, ’d) event -> unit process

             e                                                         e
     L’inconv´nient majeur du do/until de Junior vient de la difficult´ de sa finesse. Il faut
                                                                           e
examiner le corps de la construction pour comprendre comment se passe la pr´emption. De plus,
                                e                                                    e
il se marie mal avec l’ordre sup´rieur. Par exemple, le programme suivant termine apr`s n ou
n+1 instant en fonction de p :
  let process timeout n p =
    signal finished in
    do
      run p
      ||
      for i = 1 to n do pause done;
      emit finished
    until finished done
  val timeout : int -> ’a process -> unit process
                                  e        `                        `
    Remarquons enfin que la pr´emption a la SL est plus facile a implanter efficacement que
      `                                 o           e                                  e        e
celle a la Junior. Les signaux qui contrˆlent les pr´emptions ont seulement besoin d’ˆtre test´es
`                                                              e                e
a la fin de l’instant lorsque l’environnement des signaux est fig´. Il n’est pas n´cessaire de tester
les do/until pendant l’instant.

10.2.2    Les exceptions
                              e
    Ocaml dispose d’un m´canisme d’exception. Nous montrons ici comment elles sont actuel-
              e
lement trait´es en ReactiveML et une autre piste que nous avons envisag´e.    e
                                                      e            e
    Actuellement, les exceptions implantent des op´rations de pr´emption forte : lever une ex-
                                e           e            e               e               e e `
ception interrompt instantan´ment l’ex´cution. Pour ´viter les probl`mes de causalit´ li´s a
                e                             e                         e
ce type de pr´emption, les exceptions lev´es dans les expressions r´actives ne peuvent pas
e             e                                              e                      e
ˆtre rattrap´es. Ainsi une exception qui n’est pas rattrap´e au niveau instantan´ interrompt
  e                   e              e
n´cessairement l’ex´cution compl`te du programme.
                                                   e                       e
    En Junior et SugarCubes, le choix est diff´rent. Les exceptions lev´es par du code Java
                                          e                                       e
n’interrompent jamais un programme r´actif. Elles sont automatiquement rattrap´es au niveaux
                            e
des expressions instantan´es.
                                                              e            e
    Une alternative est de voir les exceptions comme des op´rations de pr´emption faible. Dans
                                        e
ce cas, il est possible de traduire le m´canisme d’exception avec des do/until et donc rattraper
                                        e
les exceptions dans des expressions r´actives.
                                                                                      e
    Nous proposons une fonction de traduction Tf [e] qui remplace les try/with pr´sents dans
                                          e
l’expression e par des do/until. L’id´e de la traduction est de remplacer les constructions
                                                     e                      e
try/with par des do/until et de remplacer les lev´es d’exception par des ´missions de signaux.
      e                                                    e e
    D´finissons la fonction Tf . Cette fonction est param´tr´e par f une fonction qui filtre les
                                            e                        e              e   e
exceptions pour les transformer en des ´missions de signaux qui d´clenchent les r´cup´rateurs
d’exceptions.
                                                e
                                    10.2. Les pr´emptions                                       163

                                             e                           e    e
   Toutes les expressions ML sont encapsul´es dans un try/with qui r´cup`re toutes les ex-
                                         e              e   e
ceptions et applique la fonction f pour d´clencher les r´cup´rateurs d’exceptions.

 Tf [e] = try T [e] with x -> f x; halt        si 0   e

                            e          e                           e
Lorsqu’une exception est lev´e par l’ex´cution de e, un signal est ´mis par l’application f x puis
    e                                                                e
l’ex´cution est suspendue par l’expression halt en attendant la pr´emption.
Remarque :
                             u                 e         e
    Tout cet ajout de code coˆte cher. Il peut ˆtre ajout´ uniquement si l’expression traduite
    peut lever une exception [84].
  ´                                        e   e
  Etudions maintenant la traduction des r´cup´rateurs d’exceptions.

 Tf [try e with E -> e ] =
     signal exnE in
     do
        let f exn =
           match exn with
           | E -> emit exnE
           | _ -> f exn
        in Tf [e]
     until exnE -> Tf [e ] done

                                             e
Un nouveau signal exnE est introduit. Il est ´mit par la traduction de l’expression e si l’exception
          e                    e                     e                       e
E est lev´e. Il est donc utilis´ comme condition d’´chappement. Pour ´mettre le signal exn E
                            e
quand l’exception E est lev´e, le corps du try/with est traduit avec la fonction de filtrage f .
                                                   e         e
Cette fonction f filtre l’exception qui lui est donn´e en entr´e. Si c’est l’exception E, alors exnE
    e                                     e
est ´mis. Sinon, la fonction f est appel´e. Remarquons que si la fonction f filtre l’exception
       e                                                  e
E, la d´finition de f masque ce traitement. Ainsi, la s´mantique des try/with imbriqu´s qui    e
rattrapent les exceptions avec le try/with le plus interne est bien respect´e. e
    Regardons enfin la traduction de process e et run e. Pour toutes les autres expressions du
langage, la fonction Tf traduit seulement les sous-expressions.

 T [process e] = process (λf.Tf [e])
 Tf [run e] = run ((Tf [e]) f )

      e                                  e e
Les d´finitions de processus sont param´tr´es par une fonction de filtrage des exceptions. L’ap-
                                                                                    u
plication de processus donne la fonction de filtrage correspondant au contexte o` le processus
       e e
est ex´cut´.
                                                                         e         e
    Si nous appliquons cette transformation, le processus principal doit ˆtre appel´ par le proces-
                                    e
sus main suivant. Il interrompt l’ex´cution du programme si une exception n’est pas rattrap´e :e
  exception Exn of exn list
  let process main p =
    signal exn in
    let f x = emit exn x in
    do
      run (p f)
    until exn(x) -> raise (Exn x) done
  val main : ((exn -> unit) -> ’a process) -> ’a process
164                                       10. Discussions

                                                ee         e        e
Il collecte toutes les exceptions qui n’ont pas ´t´ rattrap´es et pr´empte le processus principal
en levant l’exception Exn.
                 e                e
    Avec cette s´mantique de pr´emption faible pour le try/with, plusieurs exceptions peuvent
e        e            e
ˆtre lev´es en parall`le. Par exemple :
  try
    try
      raise E1 || raise E2
    with E1 -> print_string "E1"
  with E2 -> print_string "E2"
                                                     e
Dans ce cas, l’exception qui remonte le plus haut pr´empte le reste du programme. Si la mˆme e
                  e                                            e
exception est lev´e deux fois, les deux exceptions sont rattrap´es mais le traitement de l’excep-
                e
tion est effectu´ une seule fois.
  try
    raise E || raise E
  with E -> print_string "E"
                                                 e                          e
    Dans la traduction, nous n’avons pas trait´ le cas des exceptions valu´es. Ces exceptions
                 e            e                    e
posent un probl`me si une mˆme exception est lev´e plusieurs fois au cours d’un instant. C’est
                         e            e
un cas similaire au probl`me de multi-´mission. Nous pouvons envisager au moins deux solutions.
           e                                             `     e
La premi`re est de fournir une fonction de combinaison a la d´claration des exceptions. Cette
                        e                 e
solution a pour inconv´nient de ne pas ˆtre compatible avec Ocaml. La seconde solution est
                      e                  e                                             e
d’appliquer en parall`le le traitement d’´chappement pour chaque exception qui est lev´e.
         e
    Le d´faut majeur de la traduction est que la construction try/with a deux comportements
    e                                                        e         e
diff´rents en fonction de son corps. Nous retombons sur le mˆme probl`me que le do/until de
                                                                              e
Junior. Si le corps du try/with est une expression ML, le traitement de l’´chappement est
              e                               e
fait instantan´ment pour ne pas changer la s´mantique de Ocaml. En revanche, si le corps est
                  e                         e                e e                              `
une expression r´active, le traitement de l’´chappement est d´cal´ d’un instant. Une solution a
         e
ce probl`me est de proposer une nouvelle construction : try/catch par exemple, qui permet de
 e     e                                        e
r´cup´rer les exceptions dans les expressions r´actives.


10.3      Les signaux
                                      e    e                   e
   La statut des signaux a beaucoup ´volu´ au cours des diff´rentes versions de ReactiveML.
       e                        e                              e
Nous pr´sentons ici leurs caract´ristiques actuelles et les diff´rents choix que nous avons envi-
   e
sag´s.

10.3.1    Liaison des noms de signaux
             e           e
   La premi`re caract´ristique que nous avons choisie et sur laquelle nous ne sommes pas
revenus est la liaison statique des noms de signaux. Illustrons cela sur l’exemple suivant :
      signal to_exec in
      begin signal s in
        await s; print_string "Static"; print_newline()
        ||
        begin signal s in
          await s; print_string "Dynamic"; print_newline()
                                      10.3. Les signaux                                       165

        ||
        await to_exec(fun_list) in List.iter (fun f -> f()) fun_list
      end
      ||
      emit to_exec (fun () -> emit s)
    end
                                           e   e                                          e
Dans l’exemple, deux signaux s sont d´clar´s l’un dans l’autre. Si le signal le plus ext´rieur est
e                                    e                     e              e
´mis, le message Static est affich´. Si c’est le signal s int´rieur qui est ´mis, le message Dynamic
                e                e                e                         e          e
est alors affich´. Sous la port´e du signal s ext´rieur, la fonction qui ´met s est ´mise sur le
                                        e    ee     e e                 e
signal to_exec. Cette fonction est r´cup´r´e et ex´cut´e sous la port´e du second s. Comme la
                                     e                        e               e      e
liaison des noms est statique, l’ex´cution de cette fonction ´met le s ext´rieur mˆme si elle est
   e e                  e          e
ex´cut´e sous la port´e du s int´rieur. Ainsi, le message Static est affich´.     e
                                                                 e
     Le choix de la liaison statique des noms de signaux est coh´rent avec la liaison des noms de
                                                            e
variables en Ocaml. De plus, cela permet d’avoir une ex´cution plus efficace des programmes.
                                             `         e `
Avec de la liaison dynamique des noms, a chaque acc`s a un signal, il faut aller rechercher dans
                  e         `                                                                e
le contexte la d´finition a laquelle le signal se rapporte, alors que dans notre cas, l’acc`s est
direct (en temps constant).
                  e             ea
     Nous avons ´galement d´j` vu que la liaison statique permettait d’utiliser le glaneur de
                              e
cellules de Ocaml pour g´rer l’allocation des signaux. Avec de la liaison dynamique, nous
          ee        e
aurions ´t´ oblig´s de manipuler explicitement l’ensemble des signaux et donc de mettre en
            e             e
place un m´canisme d’´limination des signaux inutiles.
     En revanche, un des avantages de la liaison dynamique est qu’il ne peut pas y avoir de
   e      e    e                       e                                        e
ph´nom`ne d’´chappement de port´e. En effet, si un signal sort de sa port´e, il entre alors sous
        e                                e
la port´e d’un autre signal qui le red´finit. Cela permet donc d’utiliser toutes les optimisations
                                                e
que nous avons vues pour les signaux qui n’´chappent pas de leur port´e.    e

10.3.2                                          e
          Les signaux comme des valeurs de premi`re classe
                                                             e
    En ReactiveML, les signaux sont des valeurs de premi`re classe. Cela veux dire que les
                 e            e                                                          ee
signaux peuvent ˆtre manipul´s directement. Par exemple, des listes de signaux ou une r´f´rence
                       e      ee
vers un signal peuvent ˆtre cr´´es. De plus, comme dans le π-calcul, les signaux peuvent trans-
                                                          c                              e
mettre des signaux. Dans l’exemple suivant, le signal x re¸oit le signal y sur lequel il ´met la
valeur 42 :
  await x(y) in emit y 42
               e                                            e
Dans les premi`res versions de ReactiveML, les signaux n’´tait pas des valeurs de premi`re  e
                                                                     e                    e
classe. Cette approche se mariait mal avec la nature du langage et n’´vitait pas les probl`mes
  e                     e                `          e                                 e
d’´chappement de port´e. Par exemple, a la place d’´mettre le signal, les fonctions d’´mission
                               e    e
et d’attente du signal peuvent ˆtre ´mises :
  signal x in
  signal y in
  emit x ((fun v -> emit y v), process (await y))

Remarque :
                                    e               e
   En ReactiveML, nous avons gard´ une syntaxe sp´ciale pour introduire les noms de
                                                      e
   signaux. En revanche, en ULM, les signaux sont nomm´s avec la construction let et
166                                        10. Discussions

                         e
      l’expression sig cr´e un nouveau signal sans le nommer. Cette expression sig peut se
      programmer en ReactiveML avec la fonction new_sig :
         let new_sig () = signal s in s
         val new_sig : unit -> (’a, ’a list) event


10.3.3             e
          La multi-´mission
                e      e                                               e
    Une des sp´cificit´s de ReactiveML est la gestion de la multi-´mission des signaux valu´s.     e
                                          e e                   e
Dans les autres implantations du mod`le r´actif, il y a un m´canisme qui permet de r´cup´rer e  e
                    e
toutes les valeurs ´mises pendant un instant. En Esterel, une fonction de combinaison peut
e     e                                 e                       e        e
ˆtre d´finie, mais le type des valeurs ´mises sur le signal doit ˆtre le mˆme que celui des valeurs
            c
qui sont re¸ues. En ReactiveML, avec la construction signal/default/gather/in, ces deux
                e             e               c                                     e
choix peuvent ˆtre implant´s et d’autres fa¸ons de combiner les signaux peuvent ´galement ˆtre  e
        e
propos´es.
          e   e
    La r´cup´ration de tous les valeurs d’un signal est aussi expressive que la solution propos´e.e
                                   c                           e           e            `
En effet, une fois les valeurs re¸ues, elles peuvent ensuite ˆtre combin´es. Mais a l’usage, la
  e                                         `    e                          e ee      e
d´finition de la fonction de combinaison a la d´claration du signal s’est r´v´l´e tr`s pratique.
                                                                         e               e     e e
    Avec l’utilisation de la fonction de combinaison, l’absence de multi-´mission peut ˆtre v´rifi´e
`     e                                                         e                          e
a l’ex´cution. Dans l’exemple suivant, la fonction single cr´e un signal qui s’il est ´mis plus
                         e
d’une fois par instant l`ve l’exception Multi_emission :
  exception Multi_emission

  let single () =
    signal s default None
    gather
      fun x y ->
        match y with
        | None -> Some x
        | Some _ -> raise Multi_emission
    in s
  val single : unit -> (’a, ’a option) event
                                      e
La puissance de l’analyse de causalit´ de Esterel permet de rejeter les programmes avec
      e                                        e
multi-´mission. Faire cette analyse de causalit´ pour un langage comme Ocaml nous semble
difficile.

10.3.4     e
          S´mantique du pre
                                              e           e                           e       e
    L’expression pre s est une expression bool´enne qui s’´value en vrai si le signal ´tait pr´sent
`              e e
a l’instant pr´c´dent et en faux sinon. Cette expression se compose mal avec la suspension.
Illustrons cela avec le processus danger :
  let process danger o =
    signal s in
    emit s;
    pause;
    if pre s then emit o
  val danger : (unit, ’a) event -> unit process
                                     10.3. Les signaux                                       167

´            e                         e e                        oe
Etudions la r´action de ce processus ex´cut´ dans un do/when contrˆl´ par le signal clk. Nous
  e                e
pr´sentons deux ex´cutions de ce programme en fonction des valeurs de clk :
  do run (danger o) when clk


                         1 2 3 4 5 6                       1 2 3 4 5 6
                   clk                               clk

                   s                                 s

                   o                                 o



                                                           e
Dans le chronogramme de gauche, le signal clk est pr´sent pendant deux instants successifs.
                             e                  e     e
Dans ce cas, le signal o est ´mis (pre s s’est ´valu´ en true). Dans le chronogramme de droite,
           e                                                                   e     `
clk est pr´sent un instant sur deux. Cette fois ci, le signal o n’est pas ´mis car a l’instant 4,
                                  e     e                  `               e e
lorsque l’expression pre s est ´valu´e, le statut de s a l’instant pr´c´dent est absent. Nous
                   e                         e
constatons que mˆme si le signal s est d´fini localement au processus danger, la valeur de
         e                            e
pre s d´pend de son contexte d’ex´cution.
                                                                   e
    En Esterel le comportement du processus danger est diff´rent, quelque soit le contexte
                      e e      e                                     e
dans lequel il est ex´cut´, il ´met toujours le signal o. Cette diff´rence vient de l’horloge des
                                                                         e
signaux. En Esterel, un signal a l’horloge de son contexte de d´finition. Cela signifie que
             e e
le statut pr´c´dent d’un signal est le dernier statut qu’avait le signal lorsque son contexte de
  e        e                            e                                        e
d´finition ´tait actif. Un signal est d´fini uniquement si son contexte de d´finition est actif. En
                                          e     `
ReactiveML, tous les signaux sont d´finis a tous les instants. On dit qu’il sont sur l’horloge
de base.
               e                                                       e      e
    Cette diff´rence entre Esterel et ReactiveML vient du ph´nom`ne d’´chappement dee
     e                                                                  e
port´e qui existe en ReactiveML mais pas en Esterel. Avec l’´chappement de port´e un       e
                                          e                  e   e
signal peut sortir de son contexte de d´finition et donc ˆtre ´mis sur une horloge plus rapide
                                      e
que celle sur laquelle le signal est d´fini. C’est le cas par exemple du programme suivant :
  let process scope_extrusion =
    signal x, clk in
    emit clk
    ||
    do
      signal s in
      emit x s;
      await s
    when clk
    ||
    await one x (y) in loop emit y; pause end
   ´                                          e
   Etudions maintenant le cas des signaux valu´s :
  let process no_danger o =
    signal s default 0 gather (+) in
    emit s 42;
    pause;
    emit o (pre ?s)
  val no_danger : (int, ’a) event -> unit process
168                                       10. Discussions

                                 `        e                 e
L’expression pre ?s correspond a la derni`re valeur associ´e au signal vers s. Donc ici, quelque
                      e                                                 e
soit le contexte d’ex´cution du processus no_danger, le signal o est ´mis avec la valeur 42.
   e                               e e           e
Mˆme si plusieurs instants sont ex´cut´s entre l’´mission de s et le calcul de pre ?s, la valeur
                        e                              eee
de pre ?s est la derni`re valeur du signal lorsqu’il a ´t´ ´mis.
                  e                                               e               e
     Dans la premi`re version de pre ?s que nous avions implant´e, si le signal ´tait absent a `
            e e       e                                            e                    e
l’instant pr´c´dent l’´valuation de pre ?s alors la valeur rendue ´tait la valeur par d´faut du
                          e                                                  e
signal. Mais avec cette s´mantique de pre ?s, nous retombons dans les mˆmes probl`mes dee
composition avec la suspension que pre s.

10.3.5      Les await
                                                      e                          e
    Nous terminons la discussion sur les signaux en pr´sentant les choix sur la s´mantique de
                                                                     `
await. En SL, Junior, Loft ou ULM, l’instruction await correspond a notre await/immediate.
                                                                 ee          e          e
En ReactiveML la distinction entre await et await/immediate a ´t´ conserv´e pour les mˆmes
                                                                      e
raisons que Esterel. En particulier attendre deux occurrences de s s’´crit :
  await s; await s
                         `                                   e           `
      Mais contrairement a Esterel, l’expression await s est ´quivalente a :
  await immediate s; pause
                                                                   e
alors que pour Esterel, l’instruction pause est avant le test de pr´sence :
  pause; await immediate s
                              e       e                                   e
Nous avons fait ce choix pour ˆtre coh´rent avec l’attente de signaux valu´s. Ainsi, await s est
e          `
´quivalent a :
  await s(_) in ()


10.4        e                  e e
           S´paration instantan´/r´actif
10.4.1      Le statut de signal/in et emit
           e                   e                                     e      e               e
    Le crit`re choisi pour la s´paration entre expressions instantan´es et r´actives est bas´ sur
                        e                  e
le nombre d’instants n´cessaires pour ex´cuter les expressions. Une expression qui est toujours
   e e                                 e                               e
ex´cut´e en un instant est instantan´e, sinon c’est une expression r´active. En particulier, les
expressions signal/in et emit sont des expressions instantan´es.e
                                                                                  e
    Nous n’avons pas toujours fait ce choix. Dans [68], les expressions instantan´es sont les ex-
                                    e            e                   e                e
pressions purement ML. Cette diff´rence a des r´percutions sur la pr´sentation de la s´mantique,
                 e
sur l’expressivit´ du langage et sur l’implantation.
                        e
    D’un point de vue s´mantique, interdire les constructions emit et signal dans les expressions
          e                e                                          `
instantan´es permet de pr´senter ReactiveML comme un langage a deux niveaux. Le langage
  o              e                   e
hˆte garde sa s´mantique inchang´e, et nous proposons par dessus de nouvelles constructions
 e                                                           o                         e
r´actives qui peuvent utiliser des constructions du langage hˆte. Par exemple dans la s´mantique
                        e                 e
comportementale, la r`gle pour emit, s’´crit alors :

                                        e1 ⇓ n    e2 ⇓ v
                                                 [{v}/n], true
                                  ∅               −−−→
                                      emit e1 e2 − − − − ()
                                                      S
                                   e                  e e
                            10.4. S´paration instantan´/r´actif                               169

o` la r´duction e ⇓ v est la r´action d’une expression ML. Un des avantages de cette approche
  u     e                      e
                                     ee                  o
est de conserver toutes les propri´t´s du langage hˆte. Mais en contrepartie, les constructions
             e
qui sont pr´sentes dans les deux niveaux comme let/in sont dupliqu´es.       e
                                               e                              o            e
     Dans notre approche, il n’y a plus de s´paration entre le langage hˆte et la partie r´active.
              `                                ee
Ceci oblige a refaire les preuves des propri´t´s des expressions purement ML. En contrepartie,
                                    e                            e              e      e
il n’y a qu’un seul ensemble de r`gles, ce qui donne une pr´sentation unifi´e de la s´mantique.
                                                                          e `
     D’un point de vue conception de langage, nous avons trouv´ a l’usage plus naturel de
        e       e              e                                                   e
consid´rer la d´claration et l’´mission de signal comme des expressions instantan´es. Par exemple,
il est pratique de pouvoir utiliser les fonctions de la librairie standard de Ocaml pour manipuler
                              e                                         e
les listes de signaux. Ainsi, ´mettre tous les signaux d’une liste s’´crit :
  let emit_list l = List.iter (fun x -> emit x) l
  val emit_list : (unit, ’a) event list -> unit

                              e                                             e
    Remarquons qu’avec la s´paration actuelle des expressions instantan´es, l’application de
               e                                 e                 e
fonction peut ´mettre des signaux alors que si l’´mission est limit´e aux processus, nous savons
                             e     e
que les expressions instantan´es n’´mettent pas de signaux. Nous verrons chapitre 11.5 que cela
    e         e               e
empˆche la d´finition de l’op´rateur de composition <| qui doit garantir que la partie droite
  e
n’´met pas de signaux.
                                 e                        e                       e
    Enfin, il faut noter que la s´paration a aussi des cons´quences sur l’efficacit´ de l’implan-
        ` cause de la d´claration de signaux dans les parties instantan´es, l’implantation de la
tation. A               e                                               e
        e
biblioth`que ReactiveML n’est pas thread-safe. Cela signifie que certains modules ont un ´tat e
                          e                     e      e e               e                  e
et donc deux machines r´actives ne peuvent pas ˆtre ex´cut´es en parall`le avec la biblioth`que
               e
de processus l´gers de Ocaml.
                                    e               e e              e                    e
    En effet, si plusieurs machines r´actives sont ex´cut´es simultan´ment, lors de la cr´ation
                     e                                                             e
d’un signal il faut d´terminer la machine courante. Les parties de code instantan´ ne pouvant
     e           e                            e    e    ee             e
pas ˆtre modifi´es, cette information devrait ˆtre r´cup´r´e par un m´canisme d’introspection
  u
coˆteux.

10.4.2    Processus avec une valeur de retour
                         e e                            e
   Dans les versions pr´c´dentes de ReactiveML, il ´tait interdit d’utiliser une expression
 e                                                          `     e
r´active dans la partie gauche d’un let/in. Ceci correspond a la r`gle de bonne formation :

                                          0   e1   k   e2
                                      k   let x = e1 in e2

          e                      e    e
Ainsi, il ´tait impossible de r´cup´rer la valeur d’un processus. Donc les processus n’avaient
                                                                                     e
pas le type τ process mais simplement process. Pour transmettre une valeur calcul´e par un
processus, nous utilisions les signaux. Cette approche est celle de Junior.
                                                                              e
    Pour des exemples comme les automates cellulaires ou le simulateur de r´seaux, ce choix
            e                   e e                                                     e
n’est pas p´nalisant car en g´n´ral, chaque processus a un comportement qu’il doit ex´cuter
                                                                      e
pour toujours et donc ne calcule pas de valeurs. En revanche, pour d´finir une fonction comme
                                                  e
la fonction factorielle, cela alourdit beaucoup l’´criture du programme :
  let rec process fact n res =
    pause;
    if n <= 1 then emit res 1
170                                        10. Discussions

    else
      signal res’ in
      run (fact (n-1) res’)
      ||
      await immediate one res’(x) in
      emit res (x * n)
  val fact : int -> (int, int list) event -> unit process

                 e   e                                                                  e
En utilisant la r´cup´ration des valeurs de retour des processus, le processus fact se d´finit
par :

  let rec process fact n =
    pause;
    if n <= 1 then 1
    else
      let x = run (fact (n-1)) in x * n
  val fact : int -> int process

                    `                        e
    Contrairement a ULM, nous avons gard´ une distinction entre les processus et les fonctions.
         e                        e        e
La premi`re raison est l’efficacit´ de l’ex´cution. Les fonctions combinatoires et les processus
            e       e                 e                  e
sont compil´es diff´remment. En pr´sence d’ordre sup´rieur, si nous ne pouvons pas distin-
                                                                           `       e
guer l’application de processus et l’application de fonction, cela conduit a consid´rer (et donc
compiler) toutes les fonctions comme des processus et donc produire du code moins efficace.
                                 e                        e           e            e
    De plus, si les expressions r´actives ne peuvent pas ˆtre identifi´es, des probl`mes d’ordre
  e                                                                             e
d’´valuation se posent. Dans l’exemple suivant, si g et h sont des expressions r´actives, l’ordre
  e                                               e
d’´valuation de (g 1) et (h 2) peut changer la s´mantique du programme.

  let f g h = (g 1) + (h 2)

                              e                    e                           e e
Comme en Ocaml, l’ordre d’´valuation des param`tres d’une fonction n’est pas sp´cifi´, cela
                                                   e
changerait la nature du langage si cet ordre est fix´ en ReactiveML. Donc nous ne pouvons
                                       e               e
pas utiliser le solution de ULM pour r´soudre ce probl`me.



10.4.3      e                             e
          Ex´cution du programme et code r´entrant

                                                                             e
    Dans des langages comme Junior ou ReactiveC, la fonction d’ex´cution des instants
                                                                       e
react est disponible dans le langage. C’est au programmeur de d´finir la boucle d’ex´cution e
                                                      e            e                       e
des instants. Cette approche laisse une grande libert´ dans la d´finition du mode d’ex´cution
                                                  e    e             e     e               e
du programme. Par exemple, le programme peut ˆtre ´chantillonn´ ou r´agir sur l’arriv´e d’un
e e                                          e                 `          e         e
´v´nement externe. En revanche, cette libert´ peut conduire a des probl`mes de r´entrance. La
                e                                                 e                        e
fonction react ´tant disponible dans le langage, le programme r´actif peut pendant l’ex´cution
                        e                                        e              e
d’un instant appeler r´cursivement la fonction react. Afin d’´viter ce probl`me, un langage
                            `      e                  `                                e
comme SugarCubes teste a l’ex´cution que l’appel a la fonction react n’est pas r´entrant.
                              e             e
    En ReactiveML, pour ´viter ce probl`me, nous avons choisi une solution diff´rente. Lae
fonction react n’est pas disponible dans le langage. C’est au moment de la compilation que le
                          e                    e e
processus principal est d´fini. Le compilateur g´n`re alors le code faisant progresser les instants.
                                   e                  e e
                            10.4. S´paration instantan´/r´actif                              171

 e   e
R´sum´
                                           e
    Dans ce chapitre, nous avons discut´ du choix des constructions du langage et de leur va-
                              e                              e                            e
riantes. Nous avons commenc´ par justifier le choix d’un op´rateur de composition parall`le com-
                    e          e`       e                                       e       e
mutatif et qui peut ˆtre utilis´ a l’int´rieur d’un bloc. Puis nous avons regard´ les pr´emptions
          e
et propos´ une nouvelle solution pour le traitement des exceptions. Ce chapitre se termine avec
                                        e                                  e      e
une discussion sur les signaux et la s´paration des expressions instantan´es et r´actives.
                                       Chapitre 11

                                      Extensions

                              e
    Dans ce chapitre, nous pr´sentons des extensions du langage. Certaines telles les configura-
      e e                       ea                                               `
tions ´v´nementielles existent d´j`. D’autres, comme les automates, sont encore a implanter.


11.1                   e
          Les scripts r´actifs
    Nous proposons un mode interactif pour ReactiveML 1 . Ce mode correspond a la boucle
                                                                                   `
d’interaction (ou toplevel ) de Ocaml. Dans ce mode, les programmes ReactiveML peuvent
e     e            e e         c
ˆtre d´finis et ex´cut´s de fa¸on interactive. Le toplevel (rmltop) prend des phrases Reacti-
                 e               e                e
veML en entr´e et les interpr`te. Ce mode d’ex´cution des programmes permet l’observation
                             e       e
et la mise au point de syst`mes r´actifs.
                         e                      e                                e
    Dans le monde du r´actif, ce mode d’interpr´tation de programmes reprend l’id´e des Reac-
                           e e
tive Scripts [25] de Fr´d´ric Boussinot et Laurent Hazard. La version originale de ce langage
            ee e e
de script a ´t´ r´alis´e au-dessus de ReactiveC et de Tcl-Tk. Par la suite, Jean-Fredy Sunini
             e
en a propos´ une version au-dessus de SugarCubes et Java [100].
                                   ee                                  e
    Les Reactive Scripts ont ´t´ introduits pour prototyper de mani`re interactive des com-
               e                   `   e      e
portements r´actifs sans avoir a arrˆter l’ex´cution du programme. Ainsi, il est possible de
modifier dynamiquement le comportement d’un programme.
                                            e
    Un exemple de session rmltop est donn´ figure 11.1. Cette session commence par la ligne :
  signal s;;
      e                                     e                                             e
qui d´clare un signal global s. Cette d´claration est suivie de trois informations donn´es par
         e                    ee
l’interpr`te : (1) le type inf´r´ par le compilateur ReactiveML, (2) le type de la valeur Ocaml
  e ee                   e                                                       e
g´n´r´e et (3) sa repr´sentation. Nous pourrions masquer l’implantation concr`te des signaux
et fournir des fonctions d’inspection mais lors de la mise au point des programmes il est utile
                e          `
d’avoir un acc`s direct a ces informations.
            e                              e
    Cette d´claration est suivie par la d´finition d’un processus p qui affiche Present lorsque le
              e
signal s est ´mis :
  let process p =
    await s;
    print_string "Present";
    print_newline()
   1
            `                                                e
   Je tiens a remercier Jean-Ferdy Susini de m’avoir conseill´ de profiter de la boucle d’interaction de Ocaml
pour implanter les Reactive Scripts.


                                                    173
174                                       11. Extensions


louis@vesuve:/tmp# rmltop
       ReactiveML version 1.04.04-dev
       Objective Caml version 3.08.3

# signal s;;
val s : (’_a , ’_a list) event
val s : (’_a, ’_a list) Sig_env.Record.t * ’_b list ref * ’_c list ref =
  ({Sig_env.Record.status = -2; Sig_env.Record.value = [];
    Sig_env.Record.pre_status = -2; Sig_env.Record.pre_value = [];
    Sig_env.Record.default = []; Sig_env.Record.combine = <fun>},
   {contents = []}, {contents = []})
# let process p =
    await s;
    print_string "Present";
    print_newline()
  ;;
val p : unit process
val p :
  unit ->
  (unit -> unit) ->
  Implantation.Lco_ctrl_tree_record.contol_tree ->
  unit Implantation.Lco_ctrl_tree_record.step = <fun>
# #run p;;
- : unit = ()
# #emit s ();;
- : unit = ()
Present

                                  Fig. 11.1 – Session rmltop


                                                e e
    Une instance du processus p est ensuite ex´cut´e en utilisant la directive #run p. Les di-
                                     e
rectives sont des instructions ajout´es au langage pour pouvoir interagir directement avec la
           e            e
machine r´active qui ex´cute le programme.
          e                                              e                       e
    En ex´cutant la directive #emit s le signal s est ´mis dans la machine r´active. Donc
l’instance de p qui attendait ce signal affiche le message Present.
                                                 e                    `
   La directive principale est #run p;; qui ex´cute le processus p. A partir de cette directive,
                              ee                                  e                         e
deux nouvelles directives ont ´t´ construites. La directive #emit ´met un signal et #exec ex´cute
                e
une expression r´active :

                      #emit s v;; ≡ #run (process (emit s v));;
                      #exec e;;   ≡ #run (process e);;

             e                                 o                       e
   Il existe ´galement des directives qui contrˆlent la machine d’ex´cution de programmes
 e                                                                    e       e
r´actifs. Les directives #suspend;; et #resume;; permettent d’arrˆter l’ex´cution du pro-
                                                             e
gramme et de la reprendre. #sampling n;; change la vitesse d’´chantillonnage. #step_by_step;;
                       u                   e e
passe dans un mode o` le programme est ex´cut´ instant par instant. Dans ce mode, la direc-
                                                       e
                                    11.1. Les scripts r´actifs                                     175


                                                 Rml
                                                 + Directives

                               Ocaml        rmltop

                                                         Ocaml          ocaml
                     rmlc         Rml
                                                     + Directives
                                                                      machine

   Fig. 11.2 – Structure de l’implantation du mode interactif de ReactiveML (rmltop).


               e                                           e           e
tive #step;; ex´cute un instant. Pour revenir dans le mode ´chantillonn´, il y a la directive
#sampled;;.
    Enfin, que cela soit pour ReactiveC ou les SugarCubes, les Reactive Scripts pro-
                                                     e
posent un nouveau langage avec une syntaxe et une s´mantique propres. Au contraire, pour
                                  e                                    e           e
ReactiveML tous les programmes ´crits dans le mode interactif peuvent ˆtre compil´s et tous
                                      e      e e
les programmes ReactiveML peuvent ˆtre ex´cut´s dans le mode interactif.

Implantation
                                                                                  e
    L’implantation du mode interactif de ReactiveML a la structure pr´sent´e figure 11.2.e
                                        e              e
Un processus rmltop coordonne l’ex´cution parall`le d’un compilateur rmlc et d’une boucle
                                                         e           e              e
d’interaction ocaml. Les phrases ReactiveML donn´es en entr´e sont envoy´es au compilateur
                                                                     e`
rmlc qui retourne du code Ocaml. Ce code Ocaml est envoy´ a la boucle d’interaction pour
e      e e `         e                                                         e            e
ˆtre ex´cut´. A l’int´rieur de la boucle d’interaction, il y a un toplevel qui ´value les d´finitions et
                                      e                         e          e                   e
enrichit l’environnement et il y a ´galement un processus l´ger qui ex´cute une machine r´active
            e                                        e                         e
dans le mˆme environnement. Cette machine ex´cute le programme r´actif et interpr`te les        e
                 e
directives donn´es en entr´e.e
                           e                    o            e                            e
    Comme il est montr´ dans [52], le contrˆle de l’ex´cution d’un programme r´actif est un
    e      e                       o                          e                       e
syst`me r´actif. Ainsi, le contrˆle de la machine qui ex´cute le programme r´actif se fait par
               e                                              o
un processus ´crit en ReactiveML. Le cœur du contrˆleur est le processus machine qui fait
                                     e                               e            e
passer les instants. Il est compos´ de deux modes : (1) le mode ´chantillonn´ et (2) le mode pas
`                                                                                    e
a pas. Il doit passer du premier au second lorsque le signal step_by_step est ´mis et du second
                                   e
au premier quand sampled est ´mis. Lorsque la machine est dans le premier mode, l’ex´cution    e
                                 e
est suspendue et reprise par l’´mission du signal suspend_resume.
  let process machine =
    loop
      do
        control
          loop Rml_machine.react(); pause end
        with suspend_resume
      until step_by_step done;
      do
        loop await step; Rml_machine.react() end
      until sampled done
    end
  val machine : unit process
176                                       11. Extensions

                                  e                            e                  e
La fonction Rml_machine.react() ex´cute un instant de l’interpr`te de programmes r´actifs.


11.2     Interface avec d’autres langages
                         e
    Nous avons vu qu’il ´tait possible d’appeler des fonctions Ocaml si nous connaissions leur
                                                            e         e
interface. Nous allons voir ici comment ReactiveML peut ˆtre interfac´ avec d’autres langages
                 e                               e
et plus particuli`rement avec d’autres langages r´actifs.

     e
L’exp´rience de Lucky
                                                       e     e             e
    Lucky [58] est un langage de description de syst`mes r´actifs non d´terministes. Ce lan-
        ee e         e`                                        e                    e      e
gage a ´t´ d´velopp´ a l’origine pour le test de programmes r´actifs. Il est utilis´ pour d´crire
                         e       e
l’environnement du syst`me test´ et le simuler.
         ee
    L’int´rˆt de pouvoir appeler des programmes Lucky dans un programme ReactiveML est
                                                 e    e                                    e
de construire des simulations comprenant le syst`me r´actif et son environnement ou de d´crire
                   e
toute partie non d´terministe d’une application ReactiveML.
                                                    o               e
    Un exemple simple est celui du test d’un contrˆleur de chaudi`re. Supposons que le pro-
                                     e                               e            e
cessus ReactiveML controller d´termine en fonction de la temp´rature ext´rieure s’il faut
                  e                                                                    u
allumer la chaudi`re. Nous voulons simuler ce programme dans un environnement o`, lorsque
          e            e           e
la chaudi`re est allum´e, la temp´rature de l’environnement augmente, et diminue lorsque la
       e       e
chaudi`re est ´teinte.
                         o                                 e                e
    Pour simuler le contrˆleur en ReactiveML, il faut l’ex´cuter en parall`le avec son environ-
nement :
                                              on
                        controller                            env
                                               t

                                                 e                              e       e e
   Le comportement de l’environnement n’est pas d´terministe et peut simplement ˆtre mod´lis´
avec le programme Lucky suivant :

inputs { on: bool }
outputs { t: float }
locals { delta: float ~alias 0.5 }
nodes { init: stable; s : stable }
start_node { init }

transitions {
   init -> s ~cond t = 17.0;
   s -> s ~cond
     if on
     then 0.0 <= (t - pre t) and (t - pre t) <= delta
     else -delta <= (t - pre t) and (t - pre t) <= 0.0
}

                                       e                                     e
Ce programme Lucky prend en entr´e on, la commande de la chaudi`re, et il calcule la
     e                                                      e                       `
temp´rature t. Le comportement de l’environnement est d´crit par un automate a deux ´tats. e
  e                    e                                e              e              e
L’´tat init fixe la temp´rature initiale et passe dans l’´tat s. Dans l’´tat s, la temp´rature est
                           11.2. Interface avec d’autres langages                              177

      e                                            e            e          e
donn´e par un ensemble de contraintes. Si la chaudi`re est allum´e, la temp´rature augmente
                                                         e                     c
d’une valeur comprise entre 0 et delta. Sinon, la temp´rature diminue de fa¸on similaire.
     e                                         e       `
L’ex´cution de ce programme Lucky tire al´atoirement a chaque instant une valeur pour t qui
                                               e
satisfait les contraintes en fonction de l’entr´e.
                              c                e                             `
    Nous proposons une fa¸on simple de cr´er des processus ReactiveML a partir de pro-
                                           e                  `                      e e
grammes Lucky. Par exemple, nous cr´ons un processus env a partir de l’exemple pr´c´dent
   e
en ´crivant :
  external.luc env { on: bool } { t: float } = ["heater.luc"]

                              ee                                                     `
env est le nom du processus cr´´. on et t reprennent l’interface du programme Lucky. A droite
             e                                               e
du symbole ´gal se trouve la liste des fichiers Lucky qui d´finissent le processus.
                       ee
   Le processus env cr´´ a la signature suivante :
  val env : (’a, bool) event -> (float, ’b) event -> unit process
                   e       e            e
Le premier param`tre repr´sente les entr´es du processus. Ici, c’est un signal sur lequel la valeur
         e                                  e                                   e
lue doit ˆtre de type bool. Le second param`tre est un signal sur lequel sont ´mises les valeurs
       e
calcul´es par Lucky.
                             e        e
    Ce processus env peut ˆtre utilis´ comme tous les autres processus ReactiveML. Son
                `                                                     e e
comportement a chacune de ses activations est de lire la valeur pr´c´dente du signal d’entr´e    e
     e                       e
et d’´mettre la valeur calcul´e par Lucky. Intuitivement, la traduction en ReactiveML de la
 e
d´claration du processus env est la suivante :
  let process env on t =
    let state = ref (Luc4ocaml.make ["heater.luc"]) in
    loop
      pause;
      let v = Luc4ocaml.step_se state ["on", pre ?on] in
      emit t v
    end
val env : (’a, bool) event -> (float, ’b) event -> unit process
                                                                                e
Le module Luc4ocaml est l’interface Ocaml de Lucky. Au premier instant, l’´tat du processus
                 e     `                                                    e              e
Lucky est allou´. Puis a chaque instant, la fonction de transition est appel´e avec en entr´e la
         e e                                   e      e
valeur pr´c´dente de on. La valeur ainsi calcul´e est ´mise sur t.
                            e      e                  e    e
    Dans cet exemple, l’entr´e bool´enne on est repr´sent´e par un signal qui produit des va-
          e            e                                           e          e        e
leurs bool´ennes. La pr´sence et l’absence des signaux peuvent ´galement ˆtre utilis´es pour
    e                    e                             e             e
repr´senter les flots bool´ens. Dans ce cas, il faut d´clarer l’entr´e ou la sortie avec le type
event.
  external.luc env { on: event } { t: float } = ["heater.luc"]
  val env : (’a, ’b) event -> (float, ’c) event -> unit process
                                     e
    L’interface avec Lucky est utilis´e par Ludovic Samper (France Telecom/Verimag) dans un
                e                                   e            e            e
simulateur de r´seaux de capteurs [96]. Le but du r´seau est de d´tecter la pr´sence de nuages
toxiques. Dans ce simulateur, le comportement de chaque nœud et les communications entre
                          e
les nœuds sont programm´s en ReactiveML, mais la position des nuages est programm´e         e
                            e                                       ee
en Lucky. Une fois import´s depuis Lucky, les nuages sont consid´r´s comme des processus
                                            e     ee      e
ReactiveML, ainsi des nuages peuvent ˆtre cr´´s ou d´truits dynamiquement pendant la
simulation.
178                                       11. Extensions

                                                                        e
   Nous envisageons d’interfacer ReactiveML avec d’autres langages r´actifs comme Lustre
et Lucid Synchrone en utilisant une approche similaire. Comme pour Lucky, cela per-
                         e     e
mettra d’utiliser les sp´cificit´s de ces langages pour programmer des parties de programmes
ReactiveML. Ainsi des comportements s’exprimant mieux avec une approche flots de donn´es    e
         e      e                                             e
pourrons ˆtre d´crits directement dans ces langages et compos´s au niveau ReactiveML pour
profiter de ses aspects dynamiques.
            e                                                     e
   Cette int´gration d’autres langages dans ReactiveML peut ˆtre vue comme une premi`re    e
e                                                                          e        ee e
´tape pour son utilisation comme un langage de composition de programmes r´actifs h´t´rog`nes.
                       e                       e
Une application peut ˆtre la description de sc´narios de simulation. Prenons par exemple le si-
                e                                        e                   e
mulation d’un r´seau de capteurs dont le code embarqu´ sur les capteurs est ´crit en Lustre.
                                 e                                          e e
Les capteurs sont alors combin´s entre eux et avec un environnement mod´lis´ en Lucky au
                           e                           e            e
niveau ReactiveML. L’´volution de la topologie du r´seaux est d´crite en utilisant les aspects
                     e e
dynamiques du mod`le r´actif.


11.3                   e e
         Configurations ´v´nementielles
                      e e                                                         e
    Les configurations ´v´nementielles (ou configurations) sont des expressions bool´ennes sur
     e
la pr´sence des signaux. Par exemple, l’expression :
  await ((s1 /\ s2) \/ s3)
                              e              e                     e
attend que s1 et s2 soient pr´sents simultan´ment ou que s3 soit ´mis.
                                                  e
    En ReactiveML, les configurations sont form´es de conjonctions (∧) et de disjonctions (∨).
               e         e                                                  e
Elles peuvent ˆtre utilis´es dans toutes les constructions qui testent la pr´sence d’un signal :
await, await/immediate, present, do/when, control/with et do/until. Pour le do/until,
        u                             e    ee                    ee
le cas o` la valeur des signaux est r´cup´r´e n’est pas consid´r´. Nous discuterons dans la
prochaine section de ce cas.
                                                                                 e
    Les configurations de ReactiveML ne sont pas des expressions de premi`re classe. En
                                  e
particulier, nous ne pouvons pas ´crire :
  let c = s1 /\ s2 in await c
            ee     e                e         e                                     e
Ce choix a ´t´ guid´ par des probl`mes d’inf´rence de type. Par exemple, si l’on d´finit le
                                                             e
processus my_await, alors s est de type event et ne peut pas ˆtre une configuration.
  let process my_await s = await s
  val my_await : (’a, ’b) event -> unit process
                   e        e
Nous avons envisag´ de diff´rencier l’attente d’un configuration de l’attente d’un signal en
ajoutant le symbole ? devant les signaux. Ainsi le processus await_sig qui attend un signal et
                                                                  e    e
le processus await_config qui attend une configuration pourrait ˆtre d´fini par :
  let process await_sig s = await ?s
  val await_sig : (’a, ’b) event -> unit process

  let process await_config c = await c
  val await_config : ’a configuration -> unit process
                      e e
   Les configurations ´v´nementielles existent en SugarCubes ou en Junior, mais ne sont
      e
pas pr´sentes dans des langages comme Loft et ULM. Pour le moment, les configurations de
                                                                                    e
ReactiveML sont moins expressives que celles de Junior : nous n’autorisons pas les n´gations.
                           11.4. Filtrage de la valeur des signaux                              179

           e           e                                                       e
   Le probl`me de la n´gation est qu’elle se marie mal avec les tests instantan´s. Cela pose des
     e               e
probl`mes de causalit´. Par exemple, le programme suivant n’est pas causal :
  await immediate (not s); emit s
                          e                    e                      e e
En effet, si s est suppos´ absent, alors s est ´mit. Si s est suppos´ pr´sent, la condition du
                                            e                                e
await n’est pas satisfaite donc s n’est pas ´mis. Dans tous les cas, l’hypoth`se est contredite.
        e                                     e
   De mˆme, nous ne savons pas donner de s´mantique a    `
  do emit s when (not s)
                                                      e
Pour l’expression present, la situation est un peu diff´rente. La question qui se pose est de savoir
                                      e       e e              e
quelle est la branche qui ne peut pas ˆtre ex´cut´e instantan´ment. Par exemple, l’expression :
  present not s then e1 else e2
        e               e                                           e            e
peut ex´cuter instantan´ment sa branche else et doit ajouter un d´lai avant l’ex´cution de la
                                         e                           e   e                e
branche then. De plus, si des tests de pr´sence et d’absence sont m´lang´s, l’ajout d’un d´lai
       e              e                                                          e     e e
peut d´pendre de l’ex´cution. Dans l’expression suivante, la branche then peut ˆtre ex´cut´e
          e               e                e
instantan´ment si s1 est ´mis ou avec un d´lai si s1 et s2 sont absents.
  present s1 \/ not s2 then e1 else e2
                                                                      e
    La solution que nous proposons actuellement est d’interdire les n´gations. Nous pourrions
                           e                            e
envisager des solutions diff´rentes comme interdire les n´gations uniquement dans les construc-
                                                           e
tions await/immediate, do/when et present et les autoris´es dans les constructions comme le
               e                            e    e
do/until. La n´gation ne pose pas de probl`mes s´mantiques dans les constructions qui peuvent
                                                       e e
attendre la fin d’instant pour tester leur configuration ´v´nementielle.
                                           e
    Une autre solution pour accepter les n´gation dans la construction present est de changer
    e                            e             e
sa s´mantique en ajoutant un d´lai avant l’ex´cution des deux branches dans tous les cas et
                                                              e
proposer une construction present/immediate qui aurait la s´mantique classique de present.
                                                       e
De plus la construction present deviendrait alors sym´trique.

Implantation
                         e
    L’extension de la s´mantique avec les configurations est directe. Cela se fait comme dans le
chapitre 6.4.1. En revanche, proposer une implantation efficace n’est pas facile.
                                                                     e
    La compilation d’une configuration fournit une formule bool´enne et la liste des signaux
           e                                                                  e        `
dont elle d´pend. Ainsi une expression qui teste une configuration a un acc`s direct a l’ensemble
des files d’attente dans lesquelles elle doit s’enregistrer.
                                       e
    Lorsqu’une expression est bloqu´e sur une configuration, elle n’enregistre pas directement sa
                                                            ee
fonction de transition dans les files d’attente mais une r´f´rence vers cette fonction. Lorsqu’un
                                  e         ee
signal de la configuration est ´mis, la r´f´rence est sortie de la file d’attente et la fonction de
                  e e                                                   ee                    e
transition est ex´cut´e. Si la configuration n’est pas satisfaite, la r´f´rence est enregistr´e de
nouveau dans la file d’attente. En revanche, si la configuration est satisfaite, la fonction de
                              ee                e
transition fait pointer la r´f´rence enregistr´e dans les autres files d’attente vers une fonction
                                                  e
qui ne fait rien. Ainsi, il n’y a pas besoin de d´sabonner la fonction de transition des autres files
d’attente.


11.4     Filtrage de la valeur des signaux
          a                               e                     e
    Jusqu’` maintenant, nous avons suppos´ que les motifs utilis´s dans les constructions await/in
et do/until sont exhaustifs. Nous traitons ici le comportement des motifs non exhaustifs comme
180                                        11. Extensions

await s(1) in e.
             e                                   e    ee
    La premi`re solution que nous avons propos´e a ´t´ d’afficher un avertissement de motif non
          `                                          `     e                 e
exhaustif a la compilation et produire une erreur a l’ex´cution si la valeur ´mise sur le signal
  e             e                                                              e
n’´tait pas filtr´e par le motif. Dans ce cas, l’expression await s(1) in e est ´quivalente a`
  await s(x) in let 1 = x in e

                                          e        e
    Le comportement actuellement implant´ est diff´rent. Le filtrage sert de garde. Par exemple,
                                                   e                                 e
l’expression await s(1) in e peut commencer l’ex´cution de e uniquement si s est ´mis et que
              e     `
sa valeur est ´gale a 1.
    Ce comportement permet de programmer la construction await/one/in. Une des valeurs
e                        e     e   ee                               e
´mise sur le signal peut ˆtre r´cup´r´e en filtrant la liste valeurs ´mises par la liste qui a au
           ee
moins un ´l´ment :

                    await one s(x) in ... ≡ await s(x::_) in ...

                                                       e
Si le signal s utilise la fonction de combinaison par d´faut, la construction await/one/in peut
e      e e     e
ˆtre g´n´ralis´e avec un nombre arbitraire de valeur. Par exemple, nous pouvons attendre qu’un
            e
signal soit ´mis au moins trois fois ou exactement trois fois pendant un instant :
  await s (x1 :: x2 :: x3 :: _) in ...
  await s ([x1; x2; x3]) in ...

                                                             e             `             e
Il faut remarquer l’ordre de x1, x2 et x3 ne correspond pas n´cessairement a l’ordre des ´missions
                                             e       e                e
et peut changer en fonction de l’interpr`te utilis´. Pour rester d´terministe, il faut que les
    e
op´rations faites sur ces trois valeurs soient commutatives. En particulier, nous pouvons remar-
                                        ee
quer que si les motifs qui filtrent les ´l´ments de la liste ne sont pas exhaustifs, le programme
           e
n’est pas d´terministe. Par exemple l’expression suivante n’attend pas que au moins un 42 soit
e                                  e                                                 e      e
´mis, mais que la valeur 42 soit ´mise et que la fonction de combinaison l’ait plac´e en tˆte de
la liste :
  await s(42::_) in ...

                        e         e                           e    e                   e
Nous proposerons peut-ˆtre des m´canismes de filtrage plus ´volu´ comme ceux utilis´s dans [33].
                                                ee
Ils permettent par exemple d’utiliser les propri´t´s des multi-ensembles dans le filtrage et donc de
 e                e      e e                                  e
r´soudre le probl`me pr´c´dent. Le danger de ce type de m´thode est d’encourager l’utilisation
                                                          e
de constructions du langage que nous ne savons pas ex´cuter efficacement.
     Une autre perspective moins ambitieuse est d’ajouter des gardes when dans les motifs comme
                                                                     e      e
dans la construction match/with. Attendre que la valeur 42 soit ´mise s’´crirait alors :
  await s(x when List.mem 42 x) in ...

                              e    e
Cet ajout ne pose pas de probl`me s´mantique et permet de tester des gardes arbitrairement
        e
compliqu´es.


La construction await/immediate/in
                                          e e
    Nous venons de voir que l’on peut g´n´raliser la construction await/one/in en utilisant
                        e
le filtrage. Nous allons ´tudier le cas de await/immediate/one/in pour voir si nous pouvons
               e                                    e
proposer une m´thode similaire dans le cas instantan´.
                          11.4. Filtrage de la valeur des signaux                           181

Remarque :
                   `                     e                                      e
   Contrairement a la version non imm´diate de await/one/in, le motif utilis´ dans la
                                                 e
   construction await/immediate/one/in doit ˆtre exhaustif pour ne pas causer d’erreurs
   `     e                               e               e            e           e    e
   a l’ex´cution. Ce choix est fait pour ´viter les probl`mes de non-d´terminisme ´voqu´s
     e e
   pr´c´demment.
   Nous proposons d’ajouter au langage la construction await/immediate/in dans laquelle des
                      e
contraintes sont impos´es sur la forme des motifs. Avec cette nouvelle construction, le codage
                                     e
de await/immediate/one/in est le mˆme que celui de await/one/in :

       await immediate one s(x) in ... ≡ await immediate s(x::_) in ...

                e
Nous autorisons ´galement d’attendre un nombre minimum de valeurs :
  await immediate s (x1 :: x2 :: x3 :: _) in ...
                                                                                        e
En revanche, attendre un nombre fixe de valeurs est interdit pour des raisons de causalit´. Dans
                                  e                                      e
l’exemple suivant, nous pouvons r´agir s’il y a exactement trois valeurs ´mises et dans ce cas
          e              e                              e     e e
une quatri`me valeur est ´mise ce qui contredit l’hypoth`se pr´c´dente :
  await immediate s ([x1; x2; x3]) in emit s 4
                        e   e
   Nous interdisons de r´cup´rer la valeur de la fin d’une liste :
  await immediate s (x1 :: x2 :: x3 :: x) in ...
Cette construction est un cas particulier de l’expression await immediate s (x) in ... qui
 e     e           e                       e                               e              e
r´cup`re instantan´ment toutes les valeurs ´mises pendant un instant. Par d´finition du mod`le
 e
r´actif, nous savons cette construction impossible.
                                         e
    Finalement, les seuls motifs accept´s dans la construction await/immediate/in sont les
                     ee        e
listes d’au moins n ´l´ments d´finies par :

                pattern       ::= _ | exhaustive-pattern::pattern
           exhaustive-pattern ::= _ | x | (exhaustive-pattern, exhaustive-pattern)

              e e
Configurations ´v´nementielles
                 e                    `                                  e e
    Nous nous int´ressons maintenant a la combinaison des configurations ´v´nementielles et de
    e   e
la r´cup´ration de valeurs. Nous voulons par exemple attendre que les signaux s1 et s2 soient
e             e
´mis simultan´ment et calculer leur somme :
  await s1(x) /\ s2(y) in x + y
                                    e                       e      e
    La conjonction de signaux valu´s ne cause pas de probl`mes s´mantique. Il faut que tous les
                   e                                       e         e
signaux soient pr´sents et que toutes les valeurs puissent ˆtre filtr´es pour que la configuration
soit satisfaite. Les noms introduits dans le corps du await/in sont l’union des noms introduits
par chaque motif et il faut que l’intersection des noms introduits par chaque motif soit vide.
         e                                          e
    La s´mantique de la disjonction est plus probl´matique. Illustrons cela sur un exemple :
  await s1(x) \/ s2(x) in x
                               e
Dans cet exemple, si s1 est pr´sent et s2 est absent, alors x prend la valeur de s1. Si s2 est
  e                                                               e
pr´sent et s1 est absent, alors x prend la valeur de s2. Le probl`me est quelle est la valeur
                              e        e
de x lorsque s1 et s2 sont pr´sents ? S´mantiquement, la disjonction est commutative, il n’y
182                                        11. Extensions

                         e
a pas de raison de privil´gier la valeur de s1 ou s2. Pour cette raison, nous pensons autoriser
uniquement les conjonctions dans les constructions await/in et do/until.
                                                     e
   Une autre alternative serait de proposer un op´rateur ou exclusif garantissant qu’un seul
                         e                                              e
des deux signaux est pr´sent. Nous pouvons remarquer que dans l’op´rateur ou exclusif, il y
                                            e             e           e
a un test d’absence de signal. Mais cet op´rateur peut ˆtre autoris´ dans les await/in et les
                                           e        `
do/until car le test de la condition peut ˆtre fait a la fin d’instant.



11.5                          e    e
         La composition parall`le s´quentielle
                                                                     e
    Nous avons choisi en ReactiveML que la composition parall`le soit associative et commu-
                e                                                 e                       e
tative. Par cons´quent, l’ordre d’activation des branches parall`les n’est pas connu. N´anmoins,
                          e                       e                                           e
dans certain cas, il peut ˆtre utile de pouvoir sp´cifier cet ordre. C’est souvent le cas en pr´sence
d’effets de bord.
                          e                                   e    e                 e
    Nous proposons l’op´rateur |> de composition parall`le s´quentielle. Il ex´cute ses deux
                     e                                                              e e
branches en parall`le en garantissant que la branche gauche est toujours ex´cut´e avant la
                                             e
branche droite. Il permet par exemple la d´finition du processus print_instants qui affiche le
     e                          e
num´ro de l’instant avant l’ex´cution d’un processus p.

  let process print_instants p =
    let cpt = ref 0 in
    loop
      incr cpt;
      print_string ("****** Instant "^(string_of_int !cpt)^" ****** \n");
      pause
    end
    |>
    run p
  val print_instants : ’a process -> unit process

                    `     e                                       e
    Contrairement a l’op´rateur merge des SugarCubes, l’ex´cution de la branche droite d’un
                                                                               e
|> ne peut pas activer une expression de la partie gauche. Ainsi, les probl`mes de compositio-
      e e     e                      e e                                         e
nalit´ pr´sent´s chapitre 10.1 sont ´vit´s. En particulier, il est impossible d’´crire l’exemple de
                            e
la cascade inverse avec l’op´rateur |>.
                                     e                       `
    Afin de garantir l’absence de d´pendance de droite a gauche, nous n’avons pas fait d’ana-
                e                         e
lyse de causalit´. Nous utilisons un crit`re syntaxique. Tous les tests de signaux dans les par-
                        e     e
ties gauches des parall`les s´quentiels sont simplement interdits. Ainsi, les expressions qui se
                                                                     e
trouvent dans les parties gauches sont : les expressions instantan´es (0 e), loop, pause et les
                                                      e                 `
compositions ||, ; et |>. C’est une analyse grossi`re, mais elle est a fois simple et modulaire.
                                                                       ee
De plus, ReactiveML autorisant des constructions comme les r´f´rences et les signaux qui
          e                                                                    e
peuvent ´mettre des signaux, il est difficile de faire une analyse de causalit´ dans ce langage.
                        e                  e                                                   e e
    Nous avons envisag´ d’introduire l’op´rateur <| qui garantit que la branche droite est ex´cut´
    e
apr`s la branche gauche. Dans ce cas, toutes les constructions du langage dans la partie droite
        e                           e          e               e
sauf l’´mission de signal peuvent ˆtre utilis´es. Ainsi l’ex´cution de la branche droite ne peut
       e           e                                                        e
pas d´bloquer l’ex´cution d’une expression de la partie gauche. Le probl`me pour l’implantation
                                                            e
de cette construction est qu’il est difficile d’interdire les ´missions de signaux car tous les appels
                      e
de fonctions peuvent ´mettre potentiellement un signal.
                                      11.6. Automates                                         183

11.6     Automates
                            `                                                     `
    Nous souhaitons ajouter a ReactiveML une construction d’automate similaire a celle de
                                                                         e
Lucid Synchrone [34]. Voici par exemple comment nous pourrions red´finir le processus
                                     o       e                     e
machine (cf. chapitre 11.1) qui contrˆle l’ex´cution du programme r´actif dans le mode in-
teractif.
  let process machine =
    automaton
    | Sampled ->
        do
          control
            loop Rml_machine.react(); pause end
          with suspend_resume
        until step_by_step then Step_by_step done
    | Step_by_step ->
        do
          loop await step; Rml_machine.react() end
        until sampled then Sampled done
    end
  val machine : unit process

                      `       e                                                 e
C’est un automate a deux ´tats (Sampled et Step_by_step). Le premier ´tat est l’´tat ini- e
           e      `
tial. Il ex´cute a chaque instant la fonction Rml_machine.react lorsqu’il n’est pas suspendu
                                            e
par la construction control/with. Dans l’´tat Step_by_step, la fonction Rml_machine.react
           e `                                      e                       e
est appel´e a chaque fois que le signal step est ´mis. Le passage de l’´tat Sampled a l’´tat` e
                                                             e                       e
Step_by_step se fait lorsque le signal step_by_step est ´mis. Le retour dans l’´tat Sampled
                             e
se fait lorsque sampled est ´mis.
           e           e                                 e                                a
    L’entr´e dans les ´tats de cet automate se fait par r´initialisation. Cela signifie qu’` chaque
                                e                   e e         e          `
fois que l’on entre dans un ´tat son code est ex´cut´ du d´but. Ici, a chaque fois que l’on
              e
entre dans l’´tat Sampled, le control/with est actif. Si nous voulons entrer dans un ´tat ene
                e                 u       e                                   e
reprenant l’ex´cution au point o` elle en ´tait, nous pouvons utiliser l’entr´e par histoire. Dans
cet exemple, si la ligne :
        until sampled then Sampled done

           e
est remplac´e par :
        until sampled continue Sampled done

            e         e
alors l’entr´e dans l’´tat Sampled conserve le statut qu’avait la construction control/with en
           e
quittant l’´tat.
    La syntaxe des automates est la suivante :

               e ::= . . .
                      | automaton State -> do e u ...| State -> do e u end
               u ::=     until e(x) then State u
                      | until e(x) continue State u
                      | until e(x) -> e u
                      | done
184                                        11. Extensions

                                 e
Le langage des expressions est ´tendu avec la construction automaton/end. Un automate est
         e              e              e                                                      e
compos´e d’une liste d’´tats. Chaque ´tat a la forme State -> do e u. State est le nom de l’´tat.
                   e                e             e                                e
L’expression e d´finit le corps de l’´tat et u repr´sente la liste des conditions d’´chappement. Il y
                 e                                                                        e
a trois types d’´chappements : until/then, until/continue et until/->. Les trois d´finissent
       e                                                       e        e              e
des pr´emptions faibles. La forme until/then change d’´tat en r´initialisant l’´tat cible. La
                                                   e
forme until/continue entre dans un nouvel ´tat par histoire. La forme until/-> termine
     e                                        `
l’ex´cution de l’automate. Contrairement a Lucid Synchrone, il n’y a pas de pr´emption    e
                                  e                  e e
forte (unless) afin de rester coh´rent avec le mod`le r´actif.
                                                      `
     Les automates de ReactiveML par rapport a ceux de Lucid Synchrone peuvent ter-
               e                          e        e
miner leur ex´cution. Si le corps d’un ´tat se r´duit en une valeur v alors l’automate termine
           e                                     e                           e
instantan´ment et renvoie la valeur v. De mˆme, si une condition d’´chappement until/->
                                     `                           e
est satisfaite, l’automate termine a l’instant suivant en ex´cutant l’expression de traitement
   e
d’´chappement.


 e   e
R´sum´
                                       e
    Ce chapitre commence avec la pr´sentation de la boucle d’interaction de ReactiveML :
                e            e                        e                 e
rmltop. Cette m´thode d’ex´cution de programmes r´actifs reprend l’id´e des Reactive Scripts
 u                                          e               e
o` le comportement d’un processus peut ˆtre programm´ dynamiquement. Cette boucle d’in-
teraction peut servir d’outil de mise au point de programmes ReactiveML.
    L’implantation de rmltop repose sur l’utilisation de la boucle d’interaction de Ocaml dans
                        e            e e                              e    e         e
laquelle une machine r´active est ex´cut´e dans un thread. rmltop r´cup`re en entr´e le fichier
                                                   e             e ee
source ReactiveML, le compile avec rmlc et ex´cute le code g´n´r´ dans le toplevel Ocaml.
                                                            o     e                       e
    Nous pouvons remarquer que le programme qui contrˆle l’ex´cution de la machine r´active
est un programme ReactiveML.
                                   e `
    La seconde section est consacr´e a l’interface de ReactiveML avec Lucky, un langage de
                                      e                   `            e
description de comportements non d´terministes. Mise a part l’utilit´ de cette interface, cette
    e
exp´rience nous permet d’envisager d’utiliser ReactiveML comme un langage de composition
              e       e
de processus r´actifs ´crits dans plusieurs langages.
                          e   e
    Enfin, nous avons pr´sent´ de nouvelles constructions pour ReactiveML : les configurations
e e                                                                         e e
´v´nementielles, le filtrage de la valeur des signaux, la composition parall`le s´quentielle et les
automates.
                                    Chapitre 12

                                   Conclusion


12.1      e   e
         R´sum´
                        e   e
    Ce document a pr´sent´ ReactiveML un langage pour la programmation de syst`mes          e
 e                    e                           e
r´actifs. Ce langage ´tend Ocaml avec une op´ration de composition de programmes qui ne
                                     e             e                         e
terminent pas : la composition parall`le. Le mod`le de la concurrence utilis´ par ReactiveML
           e e             e e
est le mod`le r´actif de Fr´d´ric Boussinot.
                               e               e`                           e         e
    ReactiveML est particuli`rement adapt´ a la programmation de syst`mes qui ´voluent au
                                         e      ee       e
cours du temps : les processus peuvent ˆtre cr´´s et d´truits dynamiquement, et les canaux de
                                             e
communication entre les processus peuvent ´voluer dynamiquement. Ainsi le langage est utilis´   e
                        e              u                                         e     e      e
pour la simulation de r´seaux ad hoc o` la taille et la topologie ne peuvent pas ˆtre d´termin´es
statiquement.


Conception

                    e                                          e e                e e
    ReactiveML ´tend un langage de programmation g´n´raliste afin de b´n´ficier des struc-
               e                                                                 o
tures de donn´es (tableaux, enregistrements, . . .) et des structures de contrˆle (boucles, condi-
            e                                                                    e
tionnelle, r´cursion, . . .), qui sont essentielles pour programmer de gros syst`mes.
                          e e                      `                     e e          e
    Par ailleurs le mod`le r´actif correspond a nos besoins. Ce mod`le ´tant bas´ sur le mod`le  e
                  `                       e                                  e           e e
synchrone, il est a la fois simple et d´terministe. Les restrictions apport´es par le mod`le r´actif
                      e                                                    e             e
par rapport au mod`le synchrone permettent de supprimer les probl`mes de causalit´ qui sont
         `                                             e e
difficiles a analyser dans le cadre d’un langage g´n´raliste.
                                                             ee e      e
    Les choix de conception du langage ont d’abord ´t´ pr´sent´s au chapitre 2, puis ils ont
ee         e                                           `             e                   e
´t´ discut´s au chapitre 10. Ces choix se sont a la fois appuy´s sur (1) notre exp´rience de
                                              e                            e
programmation en ReactiveML, (2) la s´mantique et (3) la possibilit´ d’implanter efficacement
les nouvelles constructions propos´es. e
                                                  e                      e
    Un exemple de choix est d’avoir distingu´ les fonctions dont l’ex´cution prend du temps des
                          o                    e             e                 e             e
fonctions du langage hˆte qui sont suppos´es instantan´es. Les fonctions r´actives sont d´finies
                                  e
par des processus. Dans les d´finitions de processus, toutes les nouvelles constructions ajout´ese
`                             e          e           e                `
a ReactiveML peuvent ˆtre utilis´es. Cette s´paration permet a l’utilisateur d’identifier sim-
                          ` e                              e
plement les machines a ´tat des fonction instantan´es. Du point de vue de l’implantation, la
 e                               e                                e
s´paration garantit que l’ex´cution des fonctions instantan´es est aussi efficace que du code
Ocaml.

                                                185
186                                        12. Conclusion

 e
S´mantique

         e                                           e                          e
    La s´mantique formelle de ReactiveML est d´finie dans partie II. La s´mantique compor-
                           e        e                             e
tementale (chapitre 3) pr´sente l’ex´cution d’un instant en une r´action. Cette approche abstrait
                     `    e                                           ee              e
l’ordonnancement a l’int´rieur de l’instant. Ainsi la preuve de propri´t´s comme le d´terminisme
                 `
est plus simple a effectuer.
         e              e                                `        e           e
    La s´mantique op´rationnelle (chapitre 4) quant a elle pr´sente la r´action d’un instant
                                    e                                             e         e
comme une succession de petites r´actions. Elle permet la description des diff´rentes strat´gies
d’ordonnancement possibles d’un programme. Elle est ainsi un bon formalisme pour prouver
                                           e               e                e
la correction d’une implantation. Cette s´mantique est ´galement utilis´e au chapitre 5 pour
             u e           e
prouver la sˆret´ du syst`me de type.
                 e                    e                                  e             e
    La preuve d’´quivalence entre la s´mantique comportementale et la s´mantique op´rationnelle
       e    e `                                      e           e                     e
est pr´sent´e a la fin du chapitre 4. Les deux s´mantiques ´tant de nature diff´rente, leur
e                                       e
´quivalence offre de ce fait un cadre s´mantique large. L’utilisateur peut choisir le formalisme
                          ee`
en fonction de la propri´t´ a prouver.
                   e                                                                e    `
    De plus, ces s´mantiques prennent en compte l’ensemble du langage. Elles d´crivent a la fois
             e                                           e                                  e
les parties r´actives et combinatoire. Cela permet de d´crire formellement les signaux valu´s et
                     e            e     e     e
ainsi de mettre en ´vidence le ph´nom`ne d’´chappement de port´e.   e

      e             e
    L’´tude de la s´mantique du langage a eu un impact sur la conception du langage. L’exemple
                                                          o                         e
le plus marquant est le choix de ML comme langage hˆte. Ce choix s’est impos´ de lui mˆme      e
                           e e                              e
pour avoir un langage g´n´ralise expressif et dont la s´mantique formelle est simple. Nous
            e                                      e
avons essay´ autant que possible de garder une s´mantique simple lors de l’ajout des nouvelles
constructions.
                    e            e
    Par ailleurs, l’´tude de la s´mantique de ReactiveML permet de lever les ambigu¨ es surıt´
                                                                                     e
les constructions du langage et les interactions entre les parties combinatoires et r´actives. Ceci
permet d’augmenter la confiance dans le code produit par le compilateur.

                                                                                        e
    Enfin, dans les chapitres 6 et 7, les techniques d’implantation que nous avons utilis´es sont
  e                                        `
d´crites formellement. Ce travail permet a la fois de mieux comprendre l’implantation mais est
e               e                                        e             e e
´galement une ´tape importante pour le lien entre les s´mantiques pr´c´dentes et le code qui
      e e
est ex´cut´.


Implantation

                                 e
    La partie III du document pr´sente des techniques d’ordonnancement efficace de programmes
 e                                                e                            e
r´actifs et leur implantation. Le chapitre 6 pr´sente Glouton, la premi`re implantation du
     e     e                       e e                                                  e
mod`le r´actif que nous avons r´alis´e. Cette implantation tire son nom de l’id´e qu’il faut
                                                                     e
stocker les expressions en attente d’un signal pour pouvoir ex´cuter un programme r´actif       e
efficacement.
                                                                           e
    Dans le chapitre 7, l’implantation actuelle de ReactiveML est d´crite. Elle est bas´e sur  e
                                   e
l’utilisation d’un langage interm´diaire avec continuations : Lk . Comme pour Glouton, la
 e                   e                                                 e
s´mantique est bas´e sur l’utilisation de files d’attentes et le point d´licat est la prise en compte
                            o
des constructions de contrˆle do/when et do/until.
                                                                                    e
    La partie III se termine au chapitre 8 avec l’implantation de Lk et la pr´sentation d’une
         e                              e
biblioth`que pour la programmation r´active en Ocaml. L’implantation de L k dans un langage
                           e                       e        e
purement fonctionnel se d´duit directement des r`gles de s´mantique. Puis l’implantation efficace
                   e   e               e                         e
en Ocaml est pr´sent´e. Enfin, la pr´sentation de la biblioth`que montre comment nous avons
                                               e   e
                                        12.1. R´sum´                                         187

                % de cellules actives     0%       4%      42 %     60 %     83 %
                Ocaml                   0.74 s   0.75 s   0.76 s   0.77 s   0.77 s
                Loft                    0.02 s   0.11 s   0.93 s   1.57 s   2.09 s
                ReactiveML              0.05 s   0.08 s   0.89 s   1.46 s   1.94 s


                      e
Fig. 12.1 – Temps d’ex´cution moyen d’un instant pour un automate cellulaire de Fredkin de
taille 500x500.

      e                       e                                              `
pu exp´rimenter simplement diff´rentes techniques d’ordonnancement sans avoir a modifier le
compilateur.
                                                      ee                   e
    Du point de vue de l’ordonnancement, la propri´t´ principale pour ex´cuter efficacement un
                                                    e                                 e
programme est l’absence d’attente active. Cela ´vite de tester plusieurs fois la pr´sence d’un
  e                                        e     e
mˆme signal dont le statut ne peut pas ˆtre d´termin´.   e
                 ee                                        e e
    Cette propri´t´ s’illustre bien sur l’exemple de Fr´d´ric Boussinot des automates cellu-
laires [22]. Dans l’implantation de l’automate, les cellules inactives attendent un signal d’ac-
                                                         e e
tivation de sorte que seules les cellules actives sont ex´cut´es. La figure 12.1 compare le temps
     e                                                        e      e
d’ex´cution pour Loft, ReactiveML et une version imp´rative ´crite en Ocaml. La version
    e                 `
imp´rative parcourt a chaque instant toutes les cellules de l’automate avec des boucles for. Les
chiffres de la figure 12.1 montrent que l’implantation de ReactiveML est aussi efficace que
                        e
celle de Loft qui est ´crite en C et lorsqu’il y a peu de cellules actives, l’approche paresseuse
         e
implant´e en ReactiveML et en Loft est plus efficace que la version imp´rative.  e
                                             e
    Il est important de remarquer que l’ex´cution efficace de programmes ReactiveML ne
                                                                       e
repose pas uniquement sur les techniques d’ordonnancement. La repr´sentation de la structure
         o                                   e                                    e ` e
de contrˆle du programme pour pouvoir acc´der rapidement aux branches parall`les a ex´cuter
         e                                         e
ou l’acc`s aux signaux sont aussi des facteurs d´terminants. En ReactiveML, une attention
          e    ee      e
particuli`re a ´t´ port´e sur ces points.
                       e                       e     e
    Le simulateur de r´seau mobile ad hoc pr´sent´ chapitre 9 a permis de tester le langage sur
                                             e                                        e       ee
un exemple complet. Il est sorti de cette exp´rience que les performances de l’interpr`te ont ´t´
                  e                              e          e       e
suffisantes pour r´aliser les simulations qui int´ressaient l’´quipe r´seaux.

 e
R´alisations logicielles
                          e                                            ee e e
    Au cours de cette th`se, un travail important d’implantation a ´t´ r´alis´. Il a commenc´   e
par une implantation de Junior qui s’appelle Glouton. Cette implantation a une efficacit´         e
                                                            e
comparable avec les autres implantations de cette biblioth`que Java. Des tests de performance
     ee e e
ont ´t´ r´alis´s dans [1, 28].
    Un compilateur ReactiveML est disponible. Il prend en compte l’ensemble du langage
  e     e
pr´sent´ dans ce document et une partie des extensions du chapitre 11.
                                                                                  e    e
    Autour du langage, il existe d’autres outils comme : le mode interactif pr´sent´ au cha-
                       e                                      e                        e e
pitre 11.1, la biblioth`que Ocaml pour la programmation r´active, le mode Emacs r´alis´ par
                                                                                  ee e e
Sarah Maarek [65] et des exemples de programmes (une partie des exemples ont ´t´ r´alis´s par
Matthieu Carlier [29]).
                               e                        e
    Enfin, le langage est utilis´ pour la simulation de r´seaux mobiles ad hoc par Farid Benbadis
     e        e
de l’´quipe R´seaux et Performances du Laboratoire d’Informatique de Paris 6 (LIP6) [6, 7, 8, 67]
                                                e
et par Ludovic Samper dans le carde d’une th`se CIFRE entre France Telecom et le laboratoire
                                              e
Verimag (Grenoble) pour la simulation de r´seaux de capteurs [96].
188                                       12. Conclusion

12.2     Perspectives
                                                                             `
  Nous avons vu chapitre 11 des modifications que nous envisageons d’apporter a Reacti-
     `                     e                                  ` e
veML a court terme. Nous pr´sentons ici des axes de recherche a d´velopper.

12.2.1    La composition asynchrone
         e
    Le m´lange des aspects synchrones et asynchrones est une question importante. Le premier
                   ıt        e                              e
besoin qui apparaˆ lors du d´veloppement d’applications r´actives est la gestion asynchrone des
     e                                                        e                    e
entr´es/sorties. Actuellement, une fonction bloquante appel´e dans un processus r´actif bloque
    e                      e                                 e                           e
l’ex´cution de la machine r´active car ReactiveML est bas´ sur un ordonnancement coop´ratif.
            e                                  e        e
La biblioth`que de threads de Ocaml peut ˆtre utilis´e, mais nous souhaitons proposer des
                 e                  e e
constructions sp´cifiques mieux int´gr´es dans le langage.
                                                          `         e
    Loft et les Fair Threads proposent une solution a ce probl`me. Dans ces langages, un
              e       e e
thread peut ˆtre ex´cut´ dans un mode synchrone ou asynchrone et il peut changer de mode
              e                                 e                   e
en cours d’ex´cution. Ainsi pour faire une entr´e/sortie, on peut cr´er un thread qui permet la
communication entre les processus synchrones et leur environnement.
                                              `
    Un travail de conception de langage est a faire pour trouver des constructions qui soient
         `
simples a utiliser et suffisamment expressives. Les threads de service des Fair Threads en
                                  e                                 e
Scheme sont une proposition int´ressante [97]. Mais nous pouvons ´galement imaginer d’autres
                                                  e e
solutions comme un programme principal param´tr´ par des signaux externes.
                               e       e
    Une autre approche du m´lange r´actif/asynchrone est celle suivie par ULM. Dans ce cas,
        e    e              e          e                                 e
le mod`le r´actif est utilis´ pour la r´alisation d’applications distribu´es. Sur chaque site une
           e                       e e
machine r´active synchrone est ex´cut´e, et les communications entre les sites sont asynchrones.
En ULM, ces communications se font par migration de processus.
          ee         e e                                          e
    L’int´rˆt du mod`le r´actif pour programmer ce type de syst`me est de pouvoir donner une
 e                                                             e
s´mantique simple au comportement de chaque site tout en ´tant expressif. Il est possible par
                                                           a
exemple de faire de la reconfiguration dynamique. C’est-`-dire modifier le comportement d’une
                    e
application sans arrˆter le service qu’elle fournit.
                               e         e
    Pour ces deux types de m´lange r´actif/asynchrone, en cas de programmation de syst`mes  e
           u                         e         e                                      o
ouverts o` des processus peuvent ˆtre ajout´s dynamiquement, la question de contrˆle de res-
source se pose. En particulier comment garantir qu’un programme n’a pas des instants “trop
                                           e
longs”. Un processus dont le temps d’ex´cution d’un instant est beaucoup plus long que celui
                            e      e
des autres processus parall`les p´nalise tous les autres.
                       `e              e                    e     e
    Le premier point a ´tudier est l’´valuation de la dur´e d’ex´cution d’un instant. Puis une
         e         `                                      e
piste int´ressante a explorer est le retiming : comment d´couper un instant en ajoutant des ins-
                                                        e
tructions pause dans un programme sans changer sa s´mantique ? Cette transformation permet
                                  e
de faire des instants dont la dur´e est plus courte. Le retiming est une transformation classique
dans les circuits. Un exemple simple en ReactiveML est qu’il est toujours possible d’ajouter
                                        e                     e
des pause dans un processus compos´ d’une branche parall`le qui ne communique pas avec les
                         e
autres processus du syst`me.

12.2.2                         e           e
          Programmation de syst`mes embarqu´s
    Une autre direction de recherche est l’utilisation de ReactiveML pour la programmation de
    e            e
syst`mes temps-r´el. Il est possible d’identifier un sous-ensemble de ReactiveML pour lequel
                                            e
nous pouvons avoir des garanties temps-r´el. Ce sous-ensemble du langage doit en particulier
                                      12.2. Perspectives                                        189

e            e
ˆtre sans cr´ation dynamique de processus. Dans ce cas, comme pour Esterel, le temps de
 e                                             e               e
r´action du programme et sa consommation m´moire sont born´s. Ainsi, ReactiveML pourrait
e          e                               e
ˆtre utilis´ pour la programmation de syst`mes embarqu´s.e
                                                                                  e
    Le premier avantage de cette approche est de permettre la description du syst`me et de son
                                         e                                   e      e
environnement de simulation dans le mˆme langage. Par exemple, il peut ˆtre int´ressant de
                          e
faire une simulation de r´seaux de capteurs en ReactiveML et de raffiner le code des capteurs
       a                                                   e
jusqu’` l’obtention du code qui sera effectivement embarqu´ dans les capteurs.
                                             e               e           e               ee
    Le second avantage est l’absence de probl`mes de causalit´. Les probl`mes de causalit´ ´tant
                  `
souvent difficile a comprendre, leur absence aide au prototypage rapide des applications. Nos
    e                        e                        e         `
exp´riences nous ont montr´ que le retard pour la r´action a l’absence ne nous a pas gˆn´    e e
pour la programmation d’exemples de simulations. Il nous faudrait voir dans le cadre de la
                        e            e                                     e
programmation de syst`mes temps-r´el si cette contrainte n’est pas trop p´nalisante.
                 e e            ` e                    e              e
    Enfin pour g´n´rer du code a ex´cuter sur des syst`mes embarqu´s, il faut travailler sur
la compilation du sous-ensemble de ReactiveML d’une part pour des questions de GC et
                                                             e              a       e
d’autre part pour l’ordonnancement statique des programmes r´actifs : c’est-`-dire d´terminer
`                                         e                     e
a la compilation l’ordonnancement des diff´rents processus parall`les comme cela est fait dans
les langages synchrones classiques. De plus, l’ordonnancement statique de sous-ensembles de
              e               e         e                          e            e
programmes r´actifs pourrait ˆtre utilis´ pour augmenter l’efficacit´ des interpr`tes Reacti-
veML.

12.2.3     e
          V´rification formelle
        e               e
    La d´finition de la s´mantique formelle de ReactiveML a permis de montrer des propri´t´s     ee
             e                u e                             e             e                   ee
du langage (d´terminisme, sˆret´ du typage, . . .). Une autre ´tape est la v´rification de propri´t´s
                  e
des programmes ´crits en ReactiveML.
              e                                            e
    Une premi`re approche est l’utilisation d’outils de v´rification formelle. Le langage est cer-
tainement trop riche pour pouvoir utiliser directement des techniques de model checking pour
  e                ee                                    e
v´rifier des propri´t´s sur les programmes, les bases s´mantiques de ReactiveML permettent
     e                               e ` e                                            e
de d´finir une abstraction du mod`le a v´rifier. De plus, la composition parall`le synchrone
e                                       e     ` e
´tant simple, cela limite les espaces d’´tats a v´rifier.
                                                                                 ea
    Une seconde approche est de se placer dans un langage permettant d´j` de faire de la
  e                 e                     e e                                       e
v´rification et de l’´tendre avec le mod`le r´actif. Nous pouvons par exemple ´tendre l’atelier
                                           e
Focal [41] avec de la programmation r´active comme nous l’avons fait pour Ocaml. Focal
                             e                                    e
est un environnement de d´veloppement de programmes certifi´s permettant de m´langer pro-e
                           e                         e         e
grammes et preuves. Le d´veloppement en Focal ´tant bas´ sur des techniques de raffinement,
           e
cela ouvre ´galement la question du raffinement de programmes r´actifs.e
                                   e
                               Sixi`me partie

                                   Annexes

               ee
A Manuel de r´f´rence                                                                                                                    193
  A.1 Le compilateur ReactiveML . . . . . . . . .      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   . 193
                   e
  A.2 Syntaxe concr`te de ReactiveML . . . . . .       .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   . 194
      A.2.1 Conventions lexicales . . . . . . . . .    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   . 194
      A.2.2 Valeurs . . . . . . . . . . . . . . . .    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   . 196
      A.2.3 Noms . . . . . . . . . . . . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   . 196
      A.2.4 Expressions de type . . . . . . . . .      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   . 197
      A.2.5 Constantes . . . . . . . . . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   . 197
      A.2.6 Motifs . . . . . . . . . . . . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   . 198
      A.2.7 Expressions . . . . . . . . . . . . . .    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   . 199
              e
      A.2.8 D´finitions de types et d’exceptions        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   . 200
               e
      A.2.9 Sp´cifications de modules . . . . . .       .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   . 200
      A.2.10 Implantations de modules . . . . . .      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   . 201
                 e
      A.2.11 Unit´s de compilation . . . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   . 201

   e
B S´mantique Rewrite                                                                                                                    203
                                    Annexe A

                                ee
                     Manuel de r´f´rence

A.1     Le compilateur ReactiveML
                                                                          e
    rmlc est le compilateur pour le langage ReactiveML. Son comportement d´pend du fichier
      e
d’entr´e.
                                                                            e
Un fichier terminant par .rml est un fichier source ReactiveML. Il d´finit des types, des
                                             ` partir du fichier file.rml le compilateur produit
    valeurs, des fonctions et des processus. A
                                 e
    le fichier d’interface compil´e file.rzi et un fichier Ocaml file.ml.
Un fichier terminant par .rmli est un fichier source ReactiveML contenant l’interface
                 `
    d’un module. A partir du fichier file.rmli le compilateur produit le fichier d’interface
          e
    compil´e file.rzi et un fichier Ocaml file.mli.
Un fichier terminant par .mli est un fichier source Ocaml contenant l’interface de fonc-
                 e              `
    tions export´es par Ocaml. A partir du fichier file.mli le compilateur produit le fichier
                      e
    d’interface compil´e file.rzi
   L’utilisation classique du compilateur est

rmlc [options] -s <process> <file>.rml

 u                                   ` e
o` <process> est le nom du processus a ex´cuter. Les principales options reconnues par le
compilateur sont :
                        e                       e
      -stdlib <dir> Le r´pertoire de la biblioth`que standard.
                                                                    e
      -v Affiche la version du compilateur et le chemin de la biblioth`que standard et
          termine.
      -version Affiche la version du compilateur et termine.
                                           e
      -where Affiche le chemin de la biblioth`que standard et termine.
      -c Produit uniquement le fichier .rzi.
                            `               e          `
      -I <dir> Ajoute <dir> a la liste des r´pertoires a inclure.
                  e
      -s <proc> Ex´cute le processus principal <proc>.
               e
      -n <n> Ex´cute le processus principal au plus pendant <n> instants.
                                       e               `
      -sampling <rate> Fixe le temps d’´chantillonnage a <rate> seconds.
      -i Affiche les types.

                                                193
194                                                        ee
                                             A. Manuel de r´f´rence

        -dtypes Sauvegarde l’information de type dans le fichier <filename>.rannot.
        -help Affiche la liste des options.
                                   e          e
      Le fichier Ocaml produit peut ˆtre compil´ par :

ocamlc -I ‘rmlc -where‘ unix.cma rml_interpreter.cma <obj_files> <file>.ml


A.2                    e
          Syntaxe concr`te de ReactiveML
           e
Remarque pr´liminaire
                                                                   ee
      Cette partie du manuel est directement reprise du manuel de r´f´rence de Ocaml [63].

Notation
                                       e                    `
   La syntaxe du langage est donn´e avec une syntaxe a la BNF. Les symboles terminaux
                         ` e
ont une police machine a ´crire (comme cela). Les symboles non terminaux sont en italique
(comme cela). Les crochets [ . . .] repr´sentent des composants optionnels. Les accolades { . . .}
                                        e
    e         e               e e                                                      e
repr´sentent z´ro, un ou une r´p´tition de composants. Les accolades avec un plus repr´sentent
           e e                                     e             e
un ou une r´p´tition de composants. Les parenth`ses ( . . .) repr´sentent un regroupement.

A.2.1      Conventions lexicales
Blancs et commentaires
                                                                    e
      Les conventions pour les blancs et les commentaires sont les mˆmes que pour Ocaml.

Identificateurs


                                   ident ::= lowercase-ident | capitalized-ident
                      lowercase-ident ::= (lower | _) {letter | 0 . . . 9 | _}
                     capitalized-ident ::= upper {letter | 0 . . . 9 | _}
                                  letter ::= lower | upper
                                  lower ::= a . . . z
                                  upper ::= A . . . Z


Entiers



       integer-literal ::=    [-] (0 . . . 9) {0 . . . 9 | _}
                          |   [-] (0x | 0X) (0 . . . 9 | A . . . F | a . . . f) {0 . . . 9 | A . . . F | a . . . f | _}
                          |   [-] (0o | 0O) (0 . . . 7) {0 . . . 7 | _}
                          |   [-] (0b | 0B) (0 . . . 1) {0 . . . 1 | _}
                                                  e
                                A.2. Syntaxe concr`te de ReactiveML                                               195

        a
Nombres ` virgule flottante



  float-literal ::= [-] (0 . . . 9) {0 . . . 9 | _} [. {0 . . . 9 | _}] [(e | E) [+ | -] (0 . . . 9) {0 . . . 9 | _}]



      e
Caract`res

                   char-literal ::= ’ regular-char ’
                                   | ’ escape-sequence ’
            escape-sequence ::= \ (\ | " | ’ | n | t | b | r)
                               | \ (0 . . . 9) (0 . . . 9) (0 . . . 9)
                               | \x (0 . . . 9 | A . . . F | a . . . f) (0 . . . 9 | A . . . F | a . . . f)


   ınes de caract`res
Chaˆ             e

                                  string-literal ::= " {string-character} "
                              string-character ::= regular-char-str
                                                  | escape-sequence


           e
Symboles pr´fixes et infixes


           infix-symbol ::= (= | < | > | @ | ^ | | | & | + | - | * | / | $ | %) {operator-char}
         prefix-symbol ::= (! | ? | ~) {operator-char}
         operator-char ::= ! | $ | % | & | * | + | - | . | / | : | < | = | > | ? | @ | ^ | | | ~



       e
Mots cl´s
                                              e
   Les identificateurs suivant sont les mots cl´s de Ocaml :

  and               as                assert             asr                begin             class
  constraint        do                done               downto             else              end
  exception         external          false              for                fun               function
  functor           if                in                 include            inherit           initializer
  land              lazy              let                lor                lsl               lsr
  lxor              match             method             mod                module            mutable
  new               object            of                 open               or                private
  rec               sig               struct             then               to                true
  try               type              val                virtual            when              while
  with
196                                                 ee
                                      A. Manuel de r´f´rence

                                      e       e
La liste suivante contient les mots cl´s ajout´s par ReactiveML :

  await          control        default       dopar          emit           gather
  immediate      loop           nothing       one            pause          pre
  present        process        run           signal         until

          e                                  e
Les caract`res suivant sont aussi des mots cl´s :

        !=    #       &      &&      ’      (       )      *      +      ,         -
        -.    ->      .      ..      :      ::      :=     :>     ;      ;;        <
        <-    =       >      >]      >}     ?       ??     [      [<     [>        [|
        ]     _       ‘      {       {<     |       |]     }      ~      ||


A.2.2    Valeurs
   Les valeurs Ocaml sont aussi des valeurs ReactiveML. Les processus et les signaux sont
aussi des valeurs.


A.2.3    Noms
                                 e
   Les identificateurs sont utilis´s pour nommer plusieurs classes d’objets :
   – les noms de valeurs (value-name),
   – les constructeurs de valeurs et d’exceptions (constr-name),
   – les constructeurs de type (typeconstr-name),
   – les champs d’enregistrement (field-name),
   – les noms de modules (module-name),
                                   e                                       e
Ces espaces de noms sont distingu´s par le contexte et la casse de la premi`re lettre des identi-
ficateurs.


Nommage des objets


                     value-name ::= lowercase-ident
                                   | ( operator-name )
                   operator-name ::= prefix-symbol | infix-op
                          infix-op ::= infix-symbol
                                     | * | = | or | & | :=
                                     | mod | land | lor | lxor | lsl | lsr | asr
                     constr-name ::= capitalized-ident
                typeconstr-name ::= lowercase-ident
                      field-name ::= lowercase-ident
                    module-name ::= capitalized-ident
                                            e
                          A.2. Syntaxe concr`te de ReactiveML                              197

 ee       a                e
R´f´rence ` des objets nomm´s


                      value-path ::= value-name
                                    | module-name . value-name
                          constr ::= constr-name
                                    | module-name . constr-name
                      typeconstr ::= typeconstr-name
                                    | module-name . typeconstr-name
                            field ::= field-name
                                    | module-name . field-name



A.2.4    Expressions de type

                      typexpr ::=    ’ ident
                                 |   _
                                 |   ( typexpr )
                                 |   typexpr - > typexpr
                                 |   typexpr {* typexpr}+
                                 |   typeconstr
                                 |   typexpr typeconstr
                                 |   ( typexpr {, typexpr} ) typeconstr
                                 |   typexpr as ’ ident
                        e          e e                      e       e
 Le tableau suivant pr´sente la pr´c´dence et l’associativit´ des op´rateurs. Les constructions
                     e e               e
avec la plus forte pr´c´dence sont donn´s en premier.

                         Operator                        Associativity
                         Type constructor application    –
                         *                               –
                         ->                              right
                         as                              –

A.2.5    Constantes

                                constant ::=    integer-literal
                                            |   float-literal
                                            |   char-literal
                                            |   string-literal
                                            |   constr
                                            |   false
                                            |   true
                                            |   []
                                            |   ()
198                                           ee
                                A. Manuel de r´f´rence

A.2.6   Motifs

                 pattern ::=    value-name
                            |   _
                            |   constant
                            |   pattern as value-name
                            |   ( pattern )
                            |   ( pattern : typexpr )
                            |   pattern | pattern
                            |   constr pattern
                            |   pattern {, pattern}
                            |   { field = pattern {; field = pattern} }
                            |   [ pattern {; pattern} ]
                            |   pattern :: pattern
                            |   [| pattern {; pattern} |]
                                           e
                         A.2. Syntaxe concr`te de ReactiveML                            199

A.2.7   Expressions


 expr ::=    value-path
         |   constant
         |   ( expr )
         |   begin expr end
         |   ( expr : typexpr )
         |   expr , expr {, expr}
         |   constr expr
         |   expr :: expr
         |   [ expr {; expr} ]
         |   [| expr {; expr} |]
         |   { field = expr {; field = expr} }
         |   expr {expr}+
         |   run expr
         |   prefix-symbol expr
         |   expr infix-op expr
         |   expr . field       | expr . field <- expr
         |   expr .( expr ) | expr .( expr ) <- expr
         |   expr .[ expr ] | expr .[ expr ] <- expr
         |   if expr then expr [else expr]
         |   present expr then expr [else expr] | present expr else expr
         |   while expr do expr done
         |   for ident = expr (to | downto) expr (do | dopar) expr done
         |   expr ; expr
         |   expr || expr
         |   match expr with pattern-matching
         |   function pattern-matching
         |   fun multiple-matching
         |   process expr
         |   try expr with pattern-matching
         |   do expr until expr [( pattern ) -> expr] done
         |   do expr when expr
         |   control expr with expr
         |   await [[immediate] one] signal ( pattern ) in expr
         |   let lowercase-ident < pattern > in expr
         |   let [rec] let-binding {and let-binding} in expr
         |   signal lowercase-ident {, lowercase-ident} [default expr gather expr] in expr
         |   assert expr
         |   lazy expr
         |   emit expr [expr]
         |   await [immediate] expr
         |   pre [?] expr
         |   pause
         |   nothing
200                                                 ee
                                      A. Manuel de r´f´rence



        pattern-matching      ::= [|] pattern -> expr {| pattern -> expr}
        multiple-matching ::= {parameter}+ - > expr
              let-binding ::= [process] pattern = expr
                             | [process] value-name {parameter} [: typexpr] = expr
               parameter ::= pattern


A.2.8     e
         D´finitions de types et d’exceptions
 e
D´finitions de types


             type-definition ::= type typedef {and typedef }
                    typedef     ::= [type-params] typeconstr-name [type-information]
           type-information ::= [type-equation]
                               | [type-representation]
              type-equation ::= = typexpr
         type-representation ::= = constr-decl {| constr-decl}
                                | = { field-decl {; field-decl} }
               type-params ::= type-param
                              | ( type-param {, type-param} )
                type-param ::= ’ ident
                 constr-decl ::= constr-name
                                | constr-name of typexpr
                   field-decl ::= field-name : typexpr
                                | mutable field-name : typexpr


 e
D´finitions d’exceptions

               exception-definition ::= exception constr-name [of typexpr]
                                      | exception constr-name = constr


A.2.9      e
         Sp´cifications de modules

                        specification ::=     val value-name : typexpr
                                        |    type-definition
                                        |    exception constr-decl
                                        |    open module-name
                                           e
                         A.2. Syntaxe concr`te de ReactiveML                           201

A.2.10   Implantations de modules


  definition ::=    let [rec] let-binding {and let-binding}
               |   signal lowercase-ident {, lowercase-ident} [default expr gather expr]
               |   type-definition
               |   exception-definition
               |   open module-path



A.2.11       e
         Unit´s de compilation

                             unit-interface ::= {specification [;;]}
                       unit-implementation ::= {definition [;;]}
                                      Annexe B

                       e
                      S´mantique Rewrite

         e                                 e `     c                  e
    La s´mantique de ReactiveML donn´e a la fa¸on Rewrite est d´finie figures B.1 et B.2.
         e                          e
Cette d´finition reprend celle donn´e par F. Boussinot et J-F. Susini dans [27].
                                                                                e
    Il faut remarquer que nous annotons chaque branche de la composition parall`le avec son
                               e
statut d’activation. Ainsi l’op´rateur let/and/in a la syntaxe suivante :

                                 let x1 =α e1 and x2 =β e2 in e

    e                                                                          e
La r´action de cette expression utilise les fonctions auxiliaires γ, δ1 et δ2 d´finies par :
   –
                 γ(α, β) = susp               si      α = susp ou β = susp
                 γ(α, β) = term ((v1 , v2 )) si       α = term (v1 ) et β = term (v2 )
                 γ(α, β) = stop               sinon
   –
                 δ1 (α, β) = susp si        α = stop et β = stop ou β = term (v2 )
                 δ1 (α, β) = α     sinon
   –
                 δ2 (α, β) = susp si        β = stop et α = stop ou α = term (v1 )
                 δ2 (α, β) = β     sinon
    La construction do/until a une seconde forme : do/until∗ . Cette forme est utilis´e pour
                                                                                     e
attendre la fin d’instant.




                                                203
204                                                 e
                                                B. S´mantique Rewrite




                                                                                                         α
            0       e         e/S ⇓ v/S             e/S ⇓ n/S         n∈S                      −→
                                                                                       e1 , S − − e 1 , S
                        term (v)                                                                     α
                e, S − − v, S
                      −→                                                           −→
                                                    present e then e1 else e2 , S − − e1 , S

                                        e/S ⇓ n/S         n∈S                eoi ∈ S
                                                          susp
                                               −→
                present e then e1 else e2 , S − − present n then e1 else e2 , S

                                        e/S ⇓ n/S         n∈S                eoi ∈ S
                                                                              stop
                                                                  −→
                                   present e then e1 else e2 , S − − e2 , S

                α                                                      term (v)                                 α
              −→
      e1 , S − − e 1 , S             α = term (v)                     −→
                                                              e1 , S − − e 1 , S                            −→
                                                                                                    e2 , S − − e 2 , S
                               α                                                                α
                       −→
           e1 ;e2 , S − − e1 ;e2 , S                                                      −→
                                                                              e1 ;e2 , S − − e2 , S
                                                          α
            e/S ⇓ process e1 /S1                          −→
                                                e1 , S 1 − − e , S
                                            α                                                            stop
                                          −→
                                run e, S − − e , S                                             −→
                                                                                     pause, S − − (), S

                                e1 /S ⇓ v1 /S1      e2 /S1 ⇓ v2 /S2         n ∈ Dom(S2 )
                                                                               α
                                                                              −→
                                e[x ← n], S2 [(v1 , v2 , (false, v1 ), ∅)/n] − − e , S
                                                                                       α
                                                                     −→
                              signal x default e1 gather e2 in e, S − − e , S

                        α                             β
                  −→
          e1 , S − − e 1 , S 1                      −→
                                          e2 , S 1 − − e 2 , S 2          α = δ1 (α, β)                  β = δ2 (α, β)
                                                          γ(α, β)
                                                 −→
        let x1 =susp e1 and x2 =susp e2 in e, S − − let x1 =α e1 and x2 =β e2 in e, S2
                                                α
                    β = susp                  −→
                                     e 1 , S − − e1 , S             α = δ1 (α, β)              β = δ2 (α, β)
                                                          γ(α, β)
                                                 −→
        let x1 =susp e1 and x2 =susp e2 in e, S − − let x1 =α e1 and x2 =β e2 in e, S
                                                α
                    α = susp                  −→
                                     e 2 , S − − e2 , S             α = δ1 (α, β)              β = δ2 (α, β)
                                                          γ(α, β)
                                                 −→
        let x1 =susp e1 and x2 =susp e2 in e, S − − let x1 =α e1 and x2 =β e2 in e, S
                                                                         α
                                                                  −→
                                        e[x1 ← v1 , x2 ← v2 ], S − − e , S
                                                                                           α
                                                                                 −→
                            let x1 =term (v1 ) v1 and x2 =term (v2 ) v2 in e, S − − e , S



                                                  e
                                      Fig. B.1 – S´mantique Rewrite (1).
                                                                                               205




  e/S ⇓ n/S     n∈S           eoi ∈ S                    e/S ⇓ n/S            n∈S    eoi ∈ S
                susp                                                          stop
                 −→
do e1 when e, S − − do e1 when e, S                                   −→
                                                     do e1 when e, S − − do e1 when e, S

                                                                   term (v)
                   e/S ⇓ n/S           n∈S                    −→
                                                      e1 , S − − v, S
                                                    term (v)
                                               −→
                              do e1 when e, S − − v, S

                                                        term (v)
                           e/S ⇓ n/S              −→
                                          e1 , S − − v, S
                                                                 term (v)
                                                       −→
                       do e1 until e(x) -> e2 done, S − − v, S
                                                         susp
                           e/S ⇓ n/S             −→
                                         e1 , S − − e 1 , S
                                         susp
                                      −→
      do e1 until e(x) -> e2 done, S − − do e1 until n(x) -> e2 done, S
                                                         stop
                           e/S ⇓ n/S             −→
                                         e1 , S − − e 1 , S
                                         susp
     do e1 until e(x) -> e2 done, S − − do e1 until∗ n(x) -> e2 done, S
                                     −→

                                        eoi ∈ S
                                          susp
     do e1 until∗ n(x) -> e2 done, S − − do e1 until∗ n(x) -> e2 done, S
                                      −→

                                    eoi ∈ S         n∈S
                                             stop
      do e1 until∗ n(x) -> e2 done, S − − do e1 until n(x) -> e2 done, S
                                       −→

               eoi ∈ S      n∈S    S(n) = (d, g, p, m) v = fold g m d
                                                               stop
              do e1 until∗ n(x) -> e2 done, S − − e2 [x ← v], S
                                               −→



                                      e
                          Fig. B.2 – S´mantique Rewrite (2).
                                            Index

                                                            join(J, j, i, v), 114
D´finitions g´n´rales
 e              e e                                         wakeU p(N, W), 98
   ´ enement E, 50
   Ev´                                                      e/S ⇓ v/S , 100
     E, 50                                                  S, J, W       < k, v > −→ S , J , W     C,
     E1 E2 (intersection), 50                                   115, 116
     E1 E2 (ordre), 50                                      O < e, v > −→eoi W | C, 117
     E1 E2 (union), 50                                      S, J, W C =⇒ S , J , W , 113–114
   Multi-ensemble m                                         O W =⇒eoi W | C , 116
     f old f m v, 51                                        S, J, W C =⇒ S , J , W          C , 113
     one(m), 71                                           e
                                                         S´mantique comportementale, 51–54
                                                                    E, b
     m1 m2 (union), 47                                       N       −
                                                                  e − → e , 52, 53, 55, 71
   Ensemble noms de signaux N , 49                                   S
                                                          e               e
                                                         S´mantique op´rationnelle, 65–68
     N1 · N2 (concat´nation), 49
                         e
                                                            Γ, 66, 71, 72
   Environnement de sortie O, 51
                                                            e/S →ε e /S , 66, 71, 72
   Environnement de signaux S, 49–50
                                                            e/S → e /S , 66
     S, S d , S g , S p et S v , 49
                                                            O e →eoi e , 67, 71
                         e
     S#S (signaux ´mis entre S et S ), 98
                                                            e/S ⇒ e /S , 68
     next(S), 51
                                                         Typage
     S1 S1 (ordre), 50
                                                            k e, 48
     S + [v/n] (ajout de v dans S), 50
                                                            H e : τ , 77
Langages
   Glouton
     G, G, I, k, t et e, 93
     p, P , e, 95
   Lk (k et e), 111
   Noyau (e, c et v), 45
 e
S´mantique Glouton, 97–101
   Environnements : W et C, 98
   T r(P, id, i), 95–97
      c
   e    e , 105
   wakeU p(N, W), 98
   e/S ⇓ v/S , 100
   S, G, W        ta −→ S , G , W
                    i                     C, 99–
        101
   S, G, W C           S , G , W , 98
   S, G, W eoi S, G , W             C, 99
 e
S´mantique Lk , 113–122
   Environnements : J, W, C et F, 113
   C[x] et Ck [e], 112, 126

                                                   207
                              Bibliographie


       u                                           e                      e
 [1] Ra´l Acosta-Bermejo. Rejo - Langage d’Objets R´actifs et d’Agents. Th`se de doctorat,
     Ecole des Mines de Paris, 2003.
                                                                                          e
 [2] Roberto M. Amadio. The SL synchronous langage, revisited. Technical report, Universit´
     Paris 7, November 2005.
                              e               e e
 [3] Roberto M. Amadio, G´rard Boudol, F´d´ric Boussinot, and Ilaria Castellani. Reactive
     concurrent programming revisited. In Extended abstract presented at the workshop Alge-
     braic Process Calculi : the first twenty five years and beyond, Bertinoro, August 2005.
 [4] Andrew W. Appel. Compiling with Continuations. Cambridge University Press, 1991.
                                                  o
 [5] Joe Armstrong, Robert Virding, Claes Wikstr¨m, and Mike Williams. Concurrent Pro-
     gramming in Erlang. Prentice-Hall, second edition, 1996.
 [6] Farid Benbadis, Marcelo Dias de Amorim, and Serge Fdida. 3P : Packets for positions
     prediction. In Proceedings of IEEE INFOCOM STUDENTS WORKSHOP’05, Miama,
     FL, USA, March 2005.
                                                                   e            e
 [7] Farid Benbadis, Marcelo Dias de Amorim, and Serge Fdida. Diss´mination pr´dictive des
              e                   e              e       a
     coordonn´es pour le routage g´ographique bas´ sur l’ˆge. In Proceedings of CFIP 2005
     Conference, Bordeaux, France, March 2005.
 [8] Farid Benbadis, Marcelo Dias de Amorim, and Serge Fdida. ELIP : Embedded location
     information protocol. In Proceedings of IFIP Networking 2005 Conference, Waterloo,
     Canada, May 2005.
 [9] A. Benveniste, P. Caspi, S. Edwards, N. Halbwachs, P. Le Guernic, and R. de Simone.
     The synchronous languages twelve years later. Proceedings of the IEEE, Special issue on
     embedded systems, 91(1) :64–83, January 2003.
      e
[10] G´rard Berry. Preemption in concurrent systems. In Proceedings of the 13th Conference
     on Foundations of Software Technology and Theoretical Computer Science (FSTTCS’93),
     pages 72–93, London, UK, 1993. Springer-Verlag.
      e
[11] G´rard Berry. The constructive semantics of esterel, 1998.
       e
[12] G´rard Berry. The Esterel-V5 Language Primer. CMA and Inria, Sophia-Antipolis,
     France, June 2000.
      e
[13] G´rard Berry. The foundations of Esterel. In G. Plotkin, C. Stirling, and M. Tofte, editors,
     Proof, Language, and Interaction : Essays in Honour of Robin Milner, pages 425–454. MIT
     Press, 2000.
       e
[14] G´rard Boudol. Ulm : A core programming model for global computing. In Proceedings
     of the 13th European Symposium on Programming (ESOP’2004), pages 234–248, 2004.

                                              209
210                                        Bibliographie

 [15] F. Boussinot, J-F. Susini, F. Dang Tran, and L. Hazard. A reactive behavior framework
      for dynamic virtual worlds. In Proceedings of the sixth international conference on 3D
      Web technology, pages 69–75. ACM Press, 2001.
        e e
 [16] Fr´d´ric Boussinot. Reactive C : An extension of C to program reactive systems. Software
      Practice and Experience, 21(4) :401–428, April 1991.
        e e                e                    e
 [17] Fr´d´ric Boussinot. R´seaux de processus r´actifs. Research report 1588, INRIA, 1992.
        e e                                   e                           e
 [18] Fr´d´ric Boussinot. La programmation r´active - Application aux syst`mes communicants.
                                               ee
      Collection technique et scientifique des t´l´communications, masson edition, 1996.
        e e
 [19] Fr´d´ric Boussinot. Java Fair Threads. Research report 4139, INRIA, 2001.
        e e
 [20] Fr´d´ric Boussinot. Concurrent programming with Fair Threads : The LOFT language,
      2003.
        e e
 [21] Fr´d´ric Boussinot. FairThreads : mixing cooperative and preemptive threads in C. Re-
      search report 5039, INRIA, 2003.
        e e
 [22] Fr´d´ric Boussinot. Reactive programming of cellular automata. Technical Report 5183,
      INRIA, 2004.
        e e
 [23] Fr´d´ric Boussinot. Simulations of self replicating loops. 2004.
        e e
 [24] Fr´d´ric Boussinot and Robert de Simone. The SL synchronous language. Software
      Engineering, 22(4) :256–266, 1996.
        e e
 [25] Fr´d´ric Boussinot and Laurent Hazard. Reactive scripts. In Proceedings of the Third
      International Workshop on Real-Time Computing Systems Application (RTCSA’96), page
      270, Washington, DC, USA, 1996. IEEE Computer Society.
         e e
 [26] Fr´d´ric Boussinot and Jean-Ferdy Susini. The SugarCubes tool box : A reactive java
      framework. Software Practice and Experience, 28(4) :1531–1550, 1998.
        e e
 [27] Fr´d´ric Boussinot and Jean-Ferdy Susini. Junior rewrite semantics. 2000.
                                                                                         e
 [28] Christian Brunette. Construction et simulation graphiques de comportements : le mod`le
                    e                         e
      des Icobjs. Th`se de doctorat, Universit´ de Nice-Sophia Antipolis, 2004.
                           e                                                          e
 [29] Matthieu Carlier. D´veloppement d’applications en Reactive ML. Rapport de Magist`re,
               e
      Universit´ Paris 6, September 2004.
 [30] Paul Caspi and Marc Pouzet. A functional extension to Lustre. In M. A. Orgun and E. A.
      Ashcroft, editors, International Symposium on Languages for Intentional Programming,
      Sydney, Australia, May 3-5 1995. World Scientific.
 [31] Paul Caspi and Marc Pouzet. A Co-iterative Characterization of Synchronous Stream
      Functions. In Proceedings of Coalgebraic Methods in Computer Science (CMCS’98), Elec-
      tronic Notes in Theoretical Computer Science, March 1998.
 [32] E. Closse, M. Poize, J. Pulou, P. Venier, and D. Weil. SAXO-RT : interpreting Esterel
      semantic on a sequential execution structure. In Electronic Notes in Theoretical Computer
      Science, volume 65, pages 864–878. Elsevier Science Publishers, 2002.
                        e
 [33] Julien Cohen. Int´gration des collections topologiques et des transformations dans un
                             e                         e
      langage fonctionnel. Th`se de doctorat, Universit´ d’Evry-val d’Essonne, 2004.
                     c
 [34] Jean-Louis Cola¸o, Bruno Pagano, and Marc Pouzet. A conservative extension of syn-
      chronous data-flow with state machines. In Proceedings of ACM International Conference
      on Embedded Software (EMSOFT’05), September 2005.
                                      Bibliographie                                       211

                                    e
[35] Julien Demaria. Programmation r´active fonctionnelle avec Senior. Rapport de DEA,
     ESSI, 2001.
                                   e
[36] Damien Doligez. Conception, r´alisation et certification d’un glaneur de cellules concur-
             e                         e
     rent. Th`se de doctorat, Universit´ Paris 7, May 1995.
[37] Ulrich Drepper and Ingo Molnar. The native posix thread library for linux. 2005.
[38] Stephen A. Edwards. Compiling esterel into sequential code. In Proceedings of the 37th
     Design Automation Conference (DAC’2000), pages 322–327, June 5-9 2000.
[39] Conal Elliott and Paul Hudak. Functional reactive animation. In Proceedings of the second
     ACM SIGPLAN international conference on Functional programming (ICFP’97), pages
     263–273, New York, NY, USA, 1997. ACM Press.
       e
[40] St´phane Epardaud. Mobile reactive programming in ulm. In Proceedings of the Fifth
     ACM SIGPLAN Workshop on Scheme and Functional Programming, 2004.
[41] Focal.
     http://focal.inria.fr.
       e
[42] C´dric Fournet and Georges Gonthier. The reflexive chemical abstract machine and the
     join-calculus. In Proceedings of the 23rd ACM SIGPLAN-SIGACT symposium on Prin-
     ciples of programming languages (POPL’96), pages 372–385, New York, NY, USA, 1996.
     ACM Press.
      e
[43] C´dric Fournet and Luc Maranget. The Join-Calculus language, release 1.05. INRIA.
     http://join.inria.fr.
[44] The gnu portable threads.
     http://www.gnu.org/software/pth/.
                          e                 e        e                     e
[45] Georges Gonthier. S´mantiques et mod`les d’ex´cution des langages r´actifs synchrones ;
                 `            e
     application a Esterel. Th`se de doctorat, Ecole des Mines de Paris, 1988.
[46] James Gosling, Bill Joy, and Guy Steeleand Gilad Bracha. The Java Language Specifica-
     tion, Third Edition. Addison-Wesley, 2005.
[47] Matthias Grossglauser and Martin Vetterli. Locating nodes with EASE : Last encounter
     routing in ad hoc networks through mobility diffusion. In Proceedings of IEEE INFO-
     COM’03, March 2003.
[48] Gtk+, the GIMP toolkit.
     http://www.gtk.org.
[49] P. Le Guernic, T. Gautier, M. Le Borgne, and C. Lemaire. Programming real-time appli-
     cations with signal. Proceedings of IEEE, 79(9) :1321–1336, September 1991.
[50] Nicolas Halbwachs. Synchronous Programming of Reactive Systems. Kluwer Academic,
     1993.
[51] Nicolas Halbwachs, Paul Caspi, Pascal Raymond, and Daniel Pilaud. The synchronous
     data-flow programming language lustre. Proceedings of IEEE, 79(9) :1305–1320, Septem-
     ber 1991.
       e
[52] Gr´goire Hamon and Marc Pouzet. Un simulateur synchrone pour Lucid Synchrone. In
           e
     Journ´es Francophones des Langages Applicatifs (JFLA’99), Morzine-Avoriaz, February
     1999. INRIA.
[53] David Harel and Amir Pnueli. On the development of reactive systems. Logics and models
     of concurrent systems, pages 477–498, 1985.
212                                       Bibliographie

 [54] Fabrice Harrouet. oRis : s’immerger par le langage pour le prototypage d’univers virtuels
      `             e               e                         e
      a base d’entit´s autonomes. Th`se de doctorat, Universit´ de Bretagne Occidentale, 2000.
 [55] Laurent Hazard. Simple. An efficient implementation of Junior.
                                               e e
 [56] Laurent Hazard, Jean-Ferdy Susini, and Fr´d´ric Boussinot. The Junior reactive kernel.
      Research report 3732, INRIA, 1999.
                                               e e
 [57] Laurent Hazard, Jean-Ferdy Susini, and Fr´d´ric Boussinot. Programming with Junior.
      Research report 4027, INRIA, 2000.
 [58] Erwan Jahier and Pascal Raymond. The lucky language reference manual. Technical
                  e
      report, Unit´ Mixte de Recherche 5104 CNRS - INPG - UJF, 2004.
 [59] Gilles Kahn. The semantics of simple language for parallel programming. In Proceedings
      of IFIP 74 Conference, pages 471–475, 1974.
 [60] Brian W. Kernighan and Denis M. Ritchie. The C Programming Language. Prentice-Hall,
      Englewood Cliffs, New Jersey, 1978.
 [61] Steve Kleiman, Devang Shah, and Bart Smaalders. Programming with threads. SunSoft
      Press, Mountain View, CA, USA, 1996.
 [62] Xavier Leroy. Typage et programmation. Notes de cours de DEA, INRIA, 2001.
 [63] Xavier Leroy. The Objective Caml system release 3.09 Documentation and user’s manual.
      Technical report, INRIA, 2005.
 [64] LURC : Light ULM/reactive library for C.
      http://www-sop.inria.fr/mimosa/Stephane.Epardaud/lurc.
                                                                              e
 [65] Sarah Maarek. Mode Emacs pour Reactive ML. Rapport de Licence, Universit´ Paris 7,
      September 2004.
 [66] Louis Mandel. Aspects dynamiques dans les langages synchrones : la cas des SugarCubes.
                               e
      Rapport de DEA, Universit´ Paris 6, September 2002.
 [67] Louis Mandel and Farid Benbadis. Simulation of mobile ad hoc network protocols in
      ReactiveML. In Proceedings of Synchronous Languages, Applications, and Programming
      (SLAP’05), Edinburgh, Scotland, April 2005. Electronic Notes in Theoretical Computer
      Science.
 [68] Louis Mandel and Marc Pouzet. ReactiveML, a reactive extension to ML. In Proceedings
      of 7th ACM SIGPLAN International conference on Principles and Practice of Declarative
      Programming (PPDP’05), July 2005.
                                                                                   e
 [69] Louis Mandel and Marc Pouzet. ReactiveML, un langage pour la programmation r´active
                     e
      en ML. In Journ´es Francophones des Langages Applicatifs (JFLA’05), Obernai, France,
      March 2005. INRIA.
 [70] Florence Maraninchi. The Argos Language : Graphical Representation of Automata and
      Description of Reactive Systems. In Proceedings of the IEEE, Workshop on Visual Lan-
      guages, October 1991.
 [71] MetaOCaml.
      http://www.metaocaml.org/.
 [72] Giovanni De Micheli. Synthesis and Optimization of Digital Circuits. McGraw-Hill, 1994.
 [73] Robin Milner. A theory of type polymorphism in programming. Journal of Computer
      and System Sciences, 17(3) :348–375, 1978.
                                    Bibliographie                                     213

[74] Robin Milner. Calculi for synchrony and asynchrony. Theoretical Computer Science,
     25(3) :267–310, 1983.
[75] Robin Milner. Communicating and Mobile Systems : The π-Calculus. Cambridge Univer-
     sity Press, 1999.
[76] Robin Milner, Mads Tofte, Robert Harper, and David MacQueen. The Definition of
     Standard ML (Revised). MIT Press, 1997.
[77] Edward F. Moore. Gedanken-experiments on sequential machines. In C. E. Shannon and
     J. McCarthy, editors, Automata Studies, volume 34 of Annals of Mathematics Studies,
     pages 129–153. Princeton University Press, 1956.
[78] Network in A Box.
     http://nab.epfl.ch/.
[79] The Network Simulator.
     http://www.isi.edu/nsnam/ns.
[80] OPNET Modeler.
     http://www.opnet.com.
[81] John K. Ousterhout. Tcl and the Tk Toolkit. Addison-Wesley, 1994.
[82] John K. Ousterhout. Why threads are a bad idea (for most purposes). Invited talk,
     USENIX Technical Conference, January 1996.
                                   e               e           e
[83] Olivier Parra. Programmation r´active sur syst`mes embarqu´s. Rapport de DEA, UNSA,
     2003.
         c
[84] Fran¸ois Pessaux and Xavier Leroy. Type-based analysis of uncaught exceptions. ACM
     Transactions on Programming Languages and Systems, 22(2) :340–377, 2000.
[85] Simon Peyton Jones, editor. Haskell 98 Language and Libraries : The Revised Report.
     Cambridge University Press, April 2003.
[86] Simon Peyton Jones, Andrew Gordon, and Sigbjorn Finne. Concurrent Haskell. In Pro-
     ceedings of the 23rd ACM SIGPLAN-SIGACT symposium on Principles of programming
     languages (POPL’96), pages 295–308, New York, NY, USA, 1996. ACM Press.
[87] Benjamin C. Pierce. Types and Programming Languages. MIT Press, 2002.
[88] Gordon Plotkin. Call-by-name, call-by-value, and the λ-calculus. Theoretical Computer
     Science, 1 :125–159, 1975.
                                                                                e
[89] Dumitru Potop-Butucaru. Generation of Fast C Code from Esterel Programs. Th`se de
     doctorat, ENSMP/CMA, 2002.
[90] Marc Pouzet. Lucid Synchrone, version 3.0. LRI, 2005.
[91] Riccardo Pucella. Reactive programming in Standard ML. In Proceedings of the IEEE
     International Conference on Computer Languages, pages 48–57. IEEE Computer Society
     Press, 1998.
[92] Reactive programming.
     http://www-sop.inria.fr/mimosa/rp.
[93] John H. Reppy. Concurrent Programming in ML. Cambridge University Press, 1999.
                                                                     e
[94] Nadine Richard. Description de comportements d’agents autonomes ´voluant dans des
                          e     e
     mondes virtuels habit´s. Th`se de doctorat, ENST, 2001.
214                                       Bibliographie

                                                          e        `      e
 [95] Alexander Samarin. Application de la programmation r´active a la mod´lisation en phy-
                                      e
      sique. Rapport de DEA, Universit´ de Nice Sophia Antipolis, 2002.
 [96] Ludovic Samper, Florence Maraninchi, Laurent Mounier, and Louis Mandel. GLONEMO :
      Global and accurate formal models for the analysis of ad-hoc sensor networks. In Pro-
      ceedings of the First International Conference on Integrated Internet Ad hoc and Sensor
      Networks (InterSense’06), Nice, France, May 2006.
                          e e
 [97] Manuel Serrano, Fr´d´ric Boussinot, and Bernard Serpette. Scheme Fair Threads. In
      Proceedings of 6th ACM SIGPLAN International conference on Principles and Practice
      of Declarative Programming (PPDP’04), pages 203–214, 2004.
 [98] Programming with Java Fair Threads.
      http://www-sop.inria.fr/mimosa/rp/FairThreads/FTJava/DemosFairThreads.
 [99] Standard ML of New Jersey user’s guide.
      http://www.smlnj.org/doc.
                                     e                            e                e
[100] Jean-Ferdy Susini. L’approche r´active au dessus de Java : s´mantique et impl´mentation
                                       e
      des SugarCubes et de Junior. Th`se de doctorat, Ecole des Mines de Paris, 2001.
[101] Walid Taha. Multi-Stage Programming : Its Theory and Applications. PhD thesis, Oregon
      Graduate Institute of Science and Technology, 1999.
[102] Olivier Tardieu. Loops in Esterel : From Operational Semantics to Formally Specified
                    e
      Compilers. Th`se de doctorat, Ecole des Mines de Paris, 2004.
[103] Mads Tofte. Type inference for polymorphic references. Information and Computation,
      89(1) :1–34, 1990.
[104] Julien Verlaguet and Emmanuel Chailloux. HirondML : Fair Threads migrations for
      Objective Caml. In Proceedings of the Third International Workshop on High-level Parallel
      Programming and Applications (HLPP 2005), July 2005.
[105] Zhanyong Wan and Paul Hudak. Functional reactive programming from first principles.
      In Proceedings of the ACM SIGPLAN 2000 conference on Programming language design
      and implementation (PLDI’00), pages 242–252, New York, NY, USA, 2000. ACM Press.
[106] Andrew K. Wright. Simple imperative polymorphism. Lisp and Symbolic Computation,
      8(4) :343–355, 1995.
[107] Andrew K. Wright and Matthias Felleisen. A syntactic approach to type soundness.
      Information and Computation, 115(1) :38–94, 1994.

				
DOCUMENT INFO
Description: ut, social icon at top sidebar, ads space at header, black color background and very good with 3 column footer, 2 columns layout and right sidebar, fea