Rapport du Projet STL SPIN, from Promela to Gal



Documents pareils
Télécom Nancy Année

Rappel. Analyse de Données Structurées - Cours 12. Un langage avec des déclaration locales. Exemple d'un programme

Pour signifier qu'une classe fille hérite d'une classe mère, on utilise le mot clé extends class fille extends mère

RapidMiner. Data Mining. 1 Introduction. 2 Prise en main. Master Maths Finances 2010/ Présentation. 1.2 Ressources

Ingénierie Dirigée par les Modèles. Editeurs de modèles. (Eclipse Modeling Tools) Jean-Philippe Babau

INF2015 Développement de logiciels dans un environnement Agile. Examen intra 20 février :30 à 20:30

Conception de circuits numériques et architecture des ordinateurs

Chapitre VI- La validation de la composition.

TP n 2 Concepts de la programmation Objets Master 1 mention IL, semestre 2 Le type Abstrait Pile

Compte-rendu de projet de Système de gestion de base de données

openarchitectureware & transformation de modèle Yannick Lizzi Architecte Logiciel itemis France Mail: lizzi@itemis.de

ECLIPSE ET PDT (Php development tools)

Programmer en JAVA. par Tama

Programmation Objet - Cours II

Annexe : La Programmation Informatique

Évaluation et implémentation des langages

Plan. Exemple: Application bancaire. Introduction. OCL Object Constraint Language Le langage de contraintes d'uml

Tune Sweeper Manuel de l'utilisateur

Générer du code à partir d une description de haut niveau


CRÉER UNE BASE DE DONNÉES AVEC OPEN OFFICE BASE

Installation et prise en main

SOMMAIRE. Travailler avec les requêtes... 3

1. Introduction Création d'une macro autonome Exécuter la macro pas à pas Modifier une macro... 5

Chapitre 1 : Introduction aux bases de données

Les diagrammes de modélisation

ACTIVITÉ DE PROGRAMMATION

Institut Supérieure Aux Etudes Technologiques De Nabeul. Département Informatique

Généralités sur le Langage Java et éléments syntaxiques.

Plan du cours. Historique du langage Nouveautés de Java 7

Eclipse atelier Java

Cours Composant 2. Qualité logicielle et spécications algébriques

UEO11 COURS/TD 1. nombres entiers et réels codés en mémoire centrale. Caractères alphabétiques et caractères spéciaux.

INITIATION AU LANGAGE C SUR PIC DE MICROSHIP

Chapitre 2. Classes et objets

DSL. Domain Specific Language. À l'aide des technologies Eclipse Modeling. Goulwen Le Fur Le 23 novembre 2012

Seance 2: En respectant la méthode de programmation par contrat, implémentez les autres fonctions de jeu.

DA MOTA Anthony - Comparaison de technologies : PhoneGap VS Cordova

PHP 5.4 Développez un site web dynamique et interactif

Traitement de texte : Quelques rappels de quelques notions de base

TP1 : Initiation à Java et Eclipse

as Architecture des Systèmes d Information

Diagramme de classes

Recherche dans un tableau

Sage CRM. 7.2 Guide de Portail Client

Initiation à JAVA et à la programmation objet.

Rapport de Synthèse. Création d un Générateur de modèle PADL pour le langage C++ Sébastien Colladon

MOTEUR DE WORKFLOW Mise en oeuvre d'openwfe Version septembre 2006

Conditions : stage indemnisé, aide au logement possible, transport CEA en Ile-de-France gratuit.

Le stockage local de données en HTML5

TP : Shell Scripts. 1 Remarque générale. 2 Mise en jambe. 3 Avec des si. Systèmes et scripts

MICROINFORMATIQUE NOTE D APPLICATION 1 (REV. 2011) ARITHMETIQUE EN ASSEMBLEUR ET EN C

INTRODUCTION A JAVA. Fichier en langage machine Exécutable

Livre Blanc WebSphere Transcoding Publisher

UE Programmation Impérative Licence 2ème Année

Java Licence Professionnelle CISII,

Manuel d utilisation 26 juin Tâche à effectuer : écrire un algorithme 2

Table des matières PRESENTATION DU LANGAGE DS2 ET DE SES APPLICATIONS. Introduction

Algorithmique et Programmation, IMA

Dessiner dans Galaad FRANÇOIS PALLUT

Programmation C++ (débutant)/instructions for, while et do...while

Cours Langage C/C++ Programmation modulaire

Qu'est-ce que le BPM?

SweetyPix, mode d'emploi

I. Introduction aux fonctions : les fonctions standards

Publipostage avec Calc

Traduction des Langages : Le Compilateur Micro Java

Création d'un questionnaire (sondage)

Cours de Génie Logiciel

OCL - Object Constraint Language

1. Qu'est-ce que SQL? La maintenance des bases de données Les manipulations des bases de données... 5

Chapitre 2 Devine mon nombre!

Premiers Pas en Programmation Objet : les Classes et les Objets

Cours 1 : La compilation

Chap 4: Analyse syntaxique. Prof. M.D. RAHMANI Compilation SMI- S5 2013/14 1

Conduite et Gestion de Projet - Cahier des charges

TP 1. Prise en main du langage Python

Bernard HAMM, Évelyne LAVOISIER

Chapitre I Notions de base et outils de travail

AGRÉGATION «ÉCONOMIE ET GESTION»

Trier les ventes (sales order) avec Vtiger CRM

Ordonnancement. N: nains de jardin. X: peinture extérieure. E: électricité T: toit. M: murs. F: fondations CHAPTER 1

ESXi: Occupation RAM avec VM_Windows et VM_Linux. R. Babel, A. Ouadahi April 10, 2011

Whitepaper. Méthodologie de création de rapports personnalisés SQL Server Reporting Services

Conventions d écriture et outils de mise au point

Stockage du fichier dans une table mysql:

basée sur le cours de Bertrand Legal, maître de conférences à l ENSEIRB Olivier Augereau Formation UML

Grandes lignes ASTRÉE. Logiciels critiques. Outils de certification classiques. Inspection manuelle. Definition. Test

ORACLE TUNING PACK 11G

length : A N add : Z Z Z (n 1, n 2 ) n 1 + n 2

TP2 - Conguration réseau et commandes utiles. 1 Généralités. 2 Conguration de la machine. 2.1 Commande hostname

LES OUTILS D ALIMENTATION DU REFERENTIEL DE DB-MAIN

Projet Active Object

Langage et Concepts de Programmation Objet. 1 Attributs et Méthodes d instance ou de classe. Travaux Dirigés no2

Manuel d Utilisateur - Logiciel ModAFi. Jonathan ANJOU - Maud EYZAT - Kévin NAVARRO

1. Structure d un programme C. 2. Commentaire: /*..texte */ On utilise aussi le commentaire du C++ qui est valable pour C: 3.

Guide pour la réalisation d'un document avec Open Office Writer 2.2

Perl Console. Votre compagnon pour développer en Perl. Les Journées du Perl , 17 novembre, Lyon. Alexis Sukrieh

LE PROBLEME DU PLUS COURT CHEMIN

Transcription:

Rapport du Projet STL SPIN, from Promela to Gal Adrien Becchis, Fjorilda Gjermizi, Julia Wisniewski May 16, 2014 Projet de Master 1 STL UPMC auprès de Mr Yann Thierry-Mieg. 1

1 Introduction Le projet "Promela To Gal" a pour but de mettre en place une infrastructure pour pouvoir traduire des descriptions de processus concurrents écrits en Promela pour le simulateur Spin, vers un autre paradigme de description de système, avec GAL (Guarded Action Language), un langage relativement simple de modélisation. Ceci nous permettra de comparer les résultats des deux grandes familles de modèles checking, respectivement les méthodes explicites et celles symboliques. Ce faisant, l'utilisation du framework de développement de langages Xtext nous a permis de réaliser un éditeur enrichi du langage Promela intégré à Eclipse. Nous reviendrons dans ce rapport plus en détails sur le besoin et les langages sources, cibles, support, avant de passer en revue nos diérentes contributions. Nous avons regroupé nos contributions en quatres catégories: ˆ La première contribution a été de développer une grammaire et un métamodèle pour le langage Promela, et a servi de base pour toutes les autres contributions. Nous reviendrons sur les diérents choix faits lors de l'élaboration de la grammaire, présenterons le Métamodèle résultant avant d'en discuter certaines limites. ˆ Une grammaire et un Métamodèle, donc un ensemble de règles syntaxiques, ne sont pas susants pour s'assurer qu'un programme est correct. C'est pour cela que nous reviendrons sur notre deuxième contribution qui est le développement d'outils pour vérier les programmes. Pour cela une analyse du typage, ainsi qu'un certain nombre d'analyses statiques ont été réalisées pour s'assurer que le code Promela soit correct. ˆ S'étant appuyé sur le framework Xtext, nous avons parallèlement pu développer un éditeur eclipse doté des désormais indispensables colorisation syntaxique, auto-complétion, marquage d'erreur, etc. Nous avons personnalisé l'éditeur standard, mais aussi ajouté d'autres fonctionnalités ne venant pas par défaut avec Xtext. Nous reviendrons sur nos diérentes actions an de rendre cet éditeur à la fois plus fonctionnel et plaisant à utiliser. ˆ L'aboutissement du projet était la transformation de code Promela vers du code Gal. Dans un premier temps, nous nous pencherons sur l'infrastructure mise en place pour la traduction, ainsi que le "mapping", l'appariement entre les concepts des deux langages. Un plug-in eclipse se liant à l'éditeur a aussi été mis au point, ainsi qu'une génération de graphes décrivant les automates déduits du code Promela, représentation intermédiaire nécessaire à la traduction. Nous reviendrons ensuite sur les résultats concrets obtenus sur le "banc de test" Beem qui a servi de base de référence. Une fois ces quatre contributions amplement détaillées, nous tirerons un bilan de l'état du projet, mais aussi de nos expériences personnelles respectives. Pour nir, nous aborderons les perspectives, c'est-à-dire les améliorations qui pourraient être apportées à nos contributions. Bonne lecture 2

Plan 1 Introduction 2 2 Présentation des technologies utilisées. 4 2.1 Promela/Spin: le langage source.................................... 4 2.2 GAL: le langage cible.......................................... 7 2.3 Xtext et Xtend : Langages et framework support........................... 7 3 Méta-modèle et grammaire de Promela 10 3.1 Elaboration de la grammaire...................................... 10 3.2 Meta Modèle de Promela........................................ 12 3.3 Limites du MM.............................................. 14 4 Analyse Statique de Promela 15 4.1 Typage.................................................. 15 4.2 Validation................................................. 16 5 Éditeur avancé Promela 17 5.1 Quickxes................................................. 17 5.2 Outline and Labelling.......................................... 18 5.3 Templates................................................. 18 5.4 Formatting................................................ 19 6 Transformation ToGal 20 6.1 Objectif.................................................. 20 6.2 Mapping entre concepts Promela et Gal................................ 21 6.3 Architecture................................................ 21 6.4 Visualisation du Graphe de ot de contrôle.............................. 25 6.5 Résultats.................................................. 26 7 Conclusion 28 7.1 Bilan du projet.............................................. 28 7.2 Bilans Personnels............................................. 28 7.3 Perspectives................................................ 29 8 Annexes 30 8.1 Plugins Spin2Gal............................................. 30 8.2 Exemples de Transformation...................................... 30 8.3 Résultats Benchmark Beem....................................... 34 8.4 Outils utilisés................................................ 36 8.5 Références................................................. 36 3

2 Présentation des technologies utilisées. Dans cette partie, nous allons présenter les diérents langages et technologies utilisées. Nous décrirons dans un premier temps le langage source Promela et son outil SPIN, avant de parler du langage cible GAL vers lequel on va traduire. Ensuite nous présenterons le framework Xtext qui a été utilisé pour réaliser un MétaModèle du langage Promela; MM qui nous a servi ensuite à réaliser la transformation vers un MM GAL, préalablement développé dans un ancien PSTL aussi avec Xtext. 2.1 Promela/Spin: le langage source 2.1.1 Intro Promela (PROtocol MEta Language) est un langage pour décrire des processus communiquants an d'en vérier les propriétés. Ce langage de spécication de systèmes asynchrones a été introduit par Gerard J. Holzmann, et les modèles décris sont analysés à l'aide du vericateur SPIN (Simple Promela Interpreter) Cet outil a reçu le prestigieux Software System Award decerné par l'acm (Association for Computing Machinery) en 2001. Il est présenté comme l'outil le plus populaire pour la vérication des systèmes concurrents et a été notamment utilisé dans des logiciels utilisés en téléphonie, médecine ou exploration spatiale. 2.1.2 Spin L'outil Spin va permettre d'analyser un modèle promela, et d'éventuellement établir sa correction. Il va donc notamment de vérier l'absence de deadlock (états puits), la valeur de certains invariants ou autres propriétés décrites lors de la spécication. La vérication se fait grâce à la réalisation aléatoire d'exécution, ou l'exploration exhaustive de l'espace d'état du système. L'outil ne réalise pas directement la vérication du modèle. Il va, à la place, générer du code C pour réaliser celle-ci, ce qui est censé permettre d'économiser de la mémoire, de bénécier des optimisations du compilateur C, et d'incorporer directement du code C. (ce qui néanmoins retarde la détection de certaines erreur). De nombreuses options permettent d'accélérer et alléger le processus. Cet outil est librement accessible depuis 1991, et en est à sa version 6 depuis 2010(celui-ci évolue conjointement avec le langage puisqu'il en est en quelque sorte l'implantation de référence). 2.1.3 Langage Promela permet de spécier des processus, qui représentent les entités en concurrence d'un système distribué, et un environnement d'exécution via variables et canaux. Le comportement des processus est décrit à l'aide d'instruction et de structures de contrôles. Nous allons présenter plus en détails les principaux concepts et constructions du langage. L'environnement d'exécution. Le contexte d'exécution d'un modèle Promela repose sur deux types de constructions dont l'état va dénir l'état global du système. Celles-ci peuvent être globales, ou avoir une portée restreinte à un processus (et ainsi modéliser des données internes à un processus). C'est de cet environnement que sera déduit l'espace des états du système. Les variables Mémoires. Il s'agit des variables classiques des langages de programmation impératif, et correspondent à l'équivalent d'une case mémoire. Celles-ci sont typées et doivent être déclarées avant utilisation, si aucune valeur initiale est déclarée, ceux-ci valent zéro. La syntaxe de déclaration est la suivante int answer = 42; Les types de données supportés par promela sont les entiers, avec diérentes variantes selon le nombre de bits de l'emplacement mémoire, les tableaux, ou les structures à l'image du C. 4

Les canaux Les canaux sont déclarés par le mot chan suivi du nom de canal. Ils ont une capacité maximale et les messages sont typés. La déclaration se fait selon la syntaxe suivante: chan qname = [ 16 ] of {short Les canaux peuvent être locaux à un processus ou globaux. Il est éventuellement possible d'assurer l'exclusivité de l'émission ou réception à un processus particulier. Les Processus Les processus représentent les entités concurrentes du système distribué que l'on cherche à modéliser. Un processus et son comportement est déni à l'aide d'un bloc proctype. Il dénit éventuellement des variables locales et réalisera un ensemble d'instructions qui pourront modier l'environnement via des aectations, ou échanges de messages sur un canal de communication. Voici un exemple d'une déclaration d'un processus basique: active[1] proctype inc() { int cpt = 2; cpt++; cpt++ Le mot clé init est réservé au bloc de la déclaration du processus initial. Celui-ci s'exécute à l'état initial du système, et est utilisé pour dynamiquement créer d'autres processus à l'aide de l'opérateur run (qui permet aussi de passer des paramètres au processus). Le mot clé active a été introduit dans les versions récentes de Promela pour permettre de déclarer directement des processus sans passer par une successions de run Instructions de modications de l'environnement L'état global du système est modiable avec trois opérations: l'aectation, l'émission et la réception de message. Aectation Comme tout langage impératif, Promela est doté de l'aectation avec sa sémantique standard. On asssigne à une variable mémoire une nouvelle valeur. Les instructions classiques d'incrémentation ++ et décrémentation -- sont également disponibles. Le transfert des messages réception. Les canaux acceptent les deux opérations de base que sont l'émission et la L'émission (send) sur un canal est représentée par le point d'exclamation. Par example : qname! expr; correspond à une émission standard, envoie la valeur de l'expression expr sur le canal nommé qname ajoutant le message en queue. La réception est elle représentée par le point d'interrogation? Par exemple, avec l'instruction qname? msg;, on récupère le message en tête du canal et on le stocke dans la variable msg. Les opérations d'émission et réception sont bloquantes si jamais le canal est respectivement plein ou vide. De manière standard, les messages sont reçus dans l'ordre qu'ils sont émis mais il existe des variantes de ces instructions notamment avec la réception aléatoire?? qui prendra au hasard un des messages disponibles. Ceci permettra notamment de simuler des canaux de communication non ables. Par défault, les messages reçus sont consommé mais il est possible d'avoir une réception non destructive avec la syntaxe suivante: keepchan? < a > A noter qu'il est éventuellement possible de discriminer les messages à la réception, ainsi l'instruction zerochan? 0 sera bloquante tant que le prochain message à recevoir ne sera pas nul. 5

Les structures de "ux de contrôle" En promela, toute instruction est bloquante si elle n'est pas exécutable, tout comme les conditions, expressions booléennes, si celles-ci s'évaluent à faux. Il existe aussi plusieurs structures de ux de contrôle: les blocs atomics(sections critiques), alternatives(selections), les boucles(iterations) et les sauts inconditionnels(goto). Les blocs Atomic Il est possibles de regrouper des instructions devant être réalisées de concert dans une construction spéciale. Le bloc atomic permet ainsi de dénir un fragment de code qui doit être exécuté de façon indivisible. atomic { /* swap the values of a and b */ tmp = b; b = a; a = tmp Si jamais une des instructions du bloc n'est pas exécutable, par exemple la réception sur canal vide, l'exécution du bloc sera interrompue le temps nécessaire, avant de reprendre son exécution. Il existe une variante dite déterministe, d_step qui, quant à elle, ne peut être interrompue et qui ne peut donc pas contenir des instructions bloquantes. Les sélections La construction if représente une alternative. Celle ci va contenir plusieurs options, des séquences précédées par ::. La première instruction d'une séquence de contrôle est appelée une garde et détermine si l'option peut être choisie ou non. Si plusieurs gardes sont vraies, comme dans l'exemple suivant si x est compris entre a et b, alors le choix est eectué de manière non déterministe. Si aucune des gardes est vraie, alors soit le if est bloquant, soit il existe une option par défaut, une séquence précédée du mot clef else. if :: (A < x) -> option1; :: (x < B) -> option2; :: else -> option_par_defaut; fi Les boucles Un boucle do est une variante de la construction if à la diérence qu'à la n de l'option choisie, le programme revient à la position de départ. Le choix va donc être répété jusqu'à ce qu'un instruction break, ou un goto soit rencontré. Une boucle do est exécutable si et seulement si, au moins une des gardes des séquences d'options est exécutable, et une option else est aussi admise. La boucle suivante modélise un simple compteur, dont le programme sortira une fois que la variable cpt vaudra 12. int cpt; do :: (cpt < 12) -> cpt++; :: (cpt == 12) -> break; od Les sauts inconditionnels Toute instruction peut être nommée à l'aide d'un label qui va la précéder. A: a++ Ceci va permettre d'eectuer des sauts inconditionnels dans le ux de contrôle à l'aide de l'instruction goto target_label qui va identier l'instruction cible. Cette instruction est toujours exécutable. Si jamais l'instruction goto est seule dans une séquence, elle est exécutée comme un skip, l'instruction sans eet qui consomme un pas d'exécution. 6

2.2 GAL: le langage cible 2.2.1 Présentation Le langage GAL (Guarded Action Language) est un langage de modélisation pour décrire des manipulations de données pour la vérication formelle de systèmes concurrents. C'est un langage de modélisation plutôt bas niveau sans notions de processus, structures ou canaux de communications. Ces derniers sont néanmoins exprimables dans ce simple langage ce qui en fait un langage intermédiaire dédié à la vérication symbolique. Ce dernier a été développé par l'équipe Move au Lip6 en tant que backend pour d'autres notations plus "confortables" et ciblant un domaine particulier. Des transformations depuis des description de réseaux de Pétri, d'automates temporisés ont déjà été développés. 2.2.2 Langage Les constructions de bases du langage GAL sont les transitions, les actions, les expressions et les variables, celles-ci étant regroupées dans des systèmes. Les transitions regroupent un certain nombre d'actions qui, généralement, consistent juste en une succession d'aectations. Toutes les variables sont globales et de types entier ou booleen, les tableaux sont aussi supportés. Une garde booléenne est éventuellement associée à la transition pour éventuellement empêcher son exécution. En plus de cette "syntaxe simpliste", la sémantique de GAL est assez simple, proche d'une structure de Kripke. Un état est associé à chaque valuation possible de l'ensemble des variables. Les transitions sont atomiques et à chaque instant une transition à la garde vraie est exécutée. Voici un petit aperçu simpliste d'un système GAL. gal forloop_inst { int var = 42; array [3] tab = (1, 2, 4) ; transition forexample [ var!= 12 ] { tab [0] = 0 ; tab [1] = 1 ; tab [2] = 2 ; Pour plus de détails, consulter la description du langage du le site ociel. 2.2.3 Outil Les spécications GAL sont analysable à l'aide de l'outil ITS de model checking symbolique. Il s'appui sur la représentation des Diagrammes de Decision (implanté à travers la librairie ddd) ITS signigie Instantiable Transition System, et est un formalisme abstrait permettant de combiner plusieurs formalismes dont GAL, les réseaux de pétri, ou automates temporisés en les uniant sous la même interface. Il permet d'analyser l'espace d'état d'un modèle, et l'accessibilité de certains états à l'aide d' its-reach Il ore aussi deux autres outils pour pouvoir vérier des propriétés de logique temporelle exprimées à l'aide des formalismes LTL (Linear Temporal Logic) et CTL (computational tree logic) Cet outil développé par notre encadrant dans l'équipe move du Lip6 et est disponible sur le site dédié aux Diagrammes de Décision. 2.3 Xtext et Xtend : Langages et framework support An de réaliser la transformation, et donc de produire toute l'infrastructure de compilation/traduction de Métamodèle nous nous sommes basés sur le framework OpenSource de developpement de langage Xtext, que ce soit de simples DSL (Domain Specic Languages) ou de nouveaux langages bien plus complexes. Nous allons introduire le framework, en présenter son utilisation, avant d'évoquer le langage Xtend, développé à l'aide d'xtext et largement utilisé pour développer toute l'infrastructure de notre langage. 7

2.3.1 Le Framework Xtext A partir d'une grammaire, Xtext va générer un parser, mais aussi un MétaModèle et les diérentes classes pour l'arbre de syntaxe abstraite, ainsi qu'un éditeur Eclipse complet et congurable. Pour ce faire, Xtext se base sur diérentes autres technologies open sources existantes. Le parser se base sur Antlr (ANother Tool for Language Recognition), framework de construction de compilateur, le MétaModèle sur EMF (Eclipse Modeling Framework), un framework de modélisation et généraion de code, et bien d'autres comme Guice (Google Juice) pour l'injection de dépendances, ou MWE (Modeling Workow Engine) pour gérer l'agencement des diérentes phases de génération de code. Pour le MétaModèle, Xtext s'appuie sur EMF comme représentation standard, et génére la description selon les formalismes Ecore et Genmodel.Le métamodèle Ecore contient l'information concernant les classes dénies, leur attributs et leurs propriétés. Le Genmodel, quant à lui, contient l'information sur la génération du code. Ceci nous permet d'avoir à la fois une API de manipulation générique des Metamodèles, mais aussi spécique à notre AST (Arbre de Syntaxe Abstraite), ansi qu'un factory pour créer les diérents éléments. Pour plus de détails sur EMF et son intégration avec Xtext voir cette documentation sur le site ociel Xtext Parmi les fonctionnalités oertes de base, on trouve tout ce qui fait le confort des IDE actuels: à savoir: la coloration syntaxique, la complétion contextuelle, l'analyse statique, le "outline" et la navigation dans le code source, l'indexation, le refactoring et le quickx, et bien d'autres. Depuis 2008, Xtext est devenu un projet Eclipse, et son Moto est "Language Development Made Easy!", tout un programme. Il a reçu en 2010 le prix du project eclipse le plus innovant et en est actuellement à sa version 2.5. 2.3.2 Développement de langage avec Xtext en pratique. La première étape pour développer le langage est d'écrire la grammaire. La syntaxe permet en même temps de dénir les diérentes règles de parsage et les constructions du langage. Extrait de la grammaire. Iteration: 'do' {Iteration ( '::' options += Sequence )+ ( '::' 'else' '->' else = Sequence )? 'od' ; La syntaxe utilise les opérateurs standards des expressions régulières pour exprimer la cardinalité. Dans cet exemple, on voit une règle nommée Iteration. Celle-ci commence avec le token do. Le {Iteration entre crochet indique qu'une structure Iteration devra être instantiée. Ensuite, une ou plusieurs règles Sequence seront invoquées, et le resultat sera accumulé dans l'attribut options. L'éventuel else -> suivi d'une séquence sera stocké dans la variable else. La règle se termine par l'utilisation d'un point virgule. La grammaire entière est dénie avec un ensemble de règles plus ou moins complexes. Une fois une première version écrite, l'infrastructure du langage doit etre générée. L'ensemble des classes pour représenter le MM sera créé. De plus, lors de la première génération, toutes les implémentations par défaut des diérents composants de l'infrastructure sont créées. Ce sont ces classes que l'on viendra compléter pour ajouter de nouvelles fonctionnalités, ou congurer celles existantes. Plusieurs projets Eclipse sont créés dont les deux principaux: xtext il s'agit du projet principal, dans lequel se trouve la grammaire (donc les classes ast générées), mais aussi tout ce qui fait le coeur du langage, c'est-à-dire le code de validation (pour vérier statiquement nos programmes), celui pour gérer la portée, la mise en forme... ui ce projet regroupe tout le code pour personnaliser l'éditeur. A savoir, les quickxes, le labelling (les noms à attribuer aux diérentes constructions du langage), l'outline (structure d'arbre résumant le programme), l'assistance contextuelle. Chacune de ces fonctionnalités est regroupée dans son propre package. 8

Parmi les autres projets, on trouve celui pour écrire les tests pour notre infrastructure de langage, un autre pour éventuellement développer un sdk (software development kit) ansi que d'autres pour gérer l'update-site. (Le site où toute installation éclipse pourra récupérer notre plug-in.) Xtext génère un ensemble de classes génériques, avec des dénitions de bases que l'on viendra redénir pour donner à l'éditeur et au langage le comportement souhaité. Des tutoriels introductifs sont aussi disponibles sur le site ociel, et n'orent qu'un très bref aperçu des premières étapes du développement d'un langage. Il existe aussi 7 implémentation de langage, en tant que modèles de références. 2.3.3 Le langage Xtend Le framework Xtext s'appuie sur un nouveau langage pour écrire nos nouveaux langages. Nous allons présenter les raisons, atouts et inconvénients de ce "GPL pour DSLs", Xtend. Pourquoi un langage de plus? Le langage Xtend a été développé par les créateurs du framework Xtext an de faciliter l'écriture du code pour supporter le langage, et de s'épargner la verbosité de Java. De ce point de vue, il peut être considéré comme du super sucre syntaxique Java, en se compilant vers du code Java 5, et en fournissant une syntaxe et des fonctionnalités rendant le code plus compact à sémantique égale, tout en ayant accès à l'ensemble de l'api Java. Il s'agit donc bien d'un "General Purpose Language". Fonctionnalités intéréssantes Xtend aide à produire un code à lecture et écriture aisées, bien plus qu'avec du Java Standard. Ceci est rendu possible grâce à l'introduction de nouvelles fonctionnalités, dont nous allons passer en revue une partie. Tout d'abord, si Xtend utilise le même système de typage que Java (ce qui lui permet d'être totalement compatible), il utilise l'inférence de type pour épargner au programmeur de spécier le type lorsque celui-ci est évident. On pourra toujours le spécier pour clarier le code, permettre une récursion, ou forcer l'utilisation d'un surtype. Ceci permet d'alléger le code en supprimant les redondances javaesques du style final Stack<PC> breakstack = new Stack<PC>(); pour val breakstack = new Stack<PC>(). La syntaxe peut aussi être allégée vu que les ; sont facultatifs, ainsi que les parenthèses des fonctions sans paramètres. De plus les get et set des accesseurs peuvent être sous entendus. Ainsi, on pourra écrire : o.corps.steps.size en lieu et place de corps.getcorps().getsteps().size(); Xtend apporte aussi les Lambdas, et ceci sans attendre Java 8. Leur syntaxe légère, et l'itérateur implicite it s'avère extrêmement utiles couplés à des méthodes foreach des collections. Ceci a été utilisé au niveau des classes de l'interface utilisateur, notamment dans les méthodes pour gérer l'outline. Ceci permet aussi d'alléger le code là où on devait faire une implémentation anonyme de l'unique méthode abstraite de l'interface cible comme dans les méthodes addlistener, run, etc. Ÿsample Une autre fonctionnalité très intéressante voire même vitale pour de la génération de code sont les templates multilignes. En bref, il s'agit de chaînes particulières permettant d'insérer à l'intérieur d'une chaîne, le résultat d'une expression, à l'image du "abc#{expression" en Ruby ou echo "Hello $USER" en shell. Ceci évite d'avoir à écrire soi-même les successions d'append sur des StringBuffer, ce qui a le don d'obstruer totalement l'intention du code et le schéma de compilation. Cependant, comme nous avons fait de la traduction via métamodèle, plutôt que d'écrire du code compilé, nous n'avons pas eu vraiment l'occasion d'en proter. Ÿsample. La dernière caractéristique originale est ce que Xtend nomme les méthodes en extensions. En résumé, il s'agit d'une notation alternative où la méthode peut être invoquée par arg1.meth(arg2,arg3) plutôt que par Classe.meth(arg1,arg2,arg3), ce qui permet notamment de chaîner les appels de fonctions et éviter des variables locales superfétatoires (pour plus de détails, se référer à la documentation). 9

Xtend permet aussi la sucharge des opérateurs, mais nous n'avons pas eu besoin de les utiliser. D'autres fonctionnalités intéréssantes existent, telles que l'opérateur elvis?: ou l'accesseur null-safe?., et l'ensemble d'entre elles pourront être découvertes en lisant la documentation ocielle. Petits Bémols à suivre. Si Xtend a l'air génial sur le papier, son utilisation vient néanmoins doucher un peu l'enthousiasme initial. Le langage est encore jeune, et mériterait de gagner en maturité (par exemple, certaines fonctionnalités de java ont été perdues sans que l'on sache pourquoi: à l'image du += et autres aectations composées (compound assignement: x+ = 2 x = x + 2 ) en passe d'être incorporées dans les nouvelles versions du langage). Cependant, le principal problème de Xtend, est que l'éditeur Eclipse associé est à ce jour encore peu fonctionnel. Son utilisation peut même être désagréable, et compenser tous les bienfaits du langage: Les messages d'erreur sont parfois cryptiques et mal localisés, le "control assist" (C-spc) laggue tellement qu'il est tout simplement inutilisable, les templates javadoc ne s'adaptent pas à la fonction commentée,... A noter aussi qu'en production, une passe supplémentaire doit être eectuée avec une phase de génération de code java. Il n'est probablement qu'une question de temps avant que ces problèmes ne soient réglés. 3 Méta-modèle et grammaire de Promela 3.1 Elaboration de la grammaire Tout le MM du langage et l'éditeur Xtext dérive de la grammaire, nous allons présenter celle-ci. Nous allons présenter notre démarche avant de nous concentrer sur quelques coins particuliers. 3.1.1 Démarche Nous avons consacré les premières semaines sur cette étape initiale, ceci jusqu'à obtenir une grammaire assez stabilisée pour commencer la transformation. Nous sommes partis d'une première grammaire sommaire gérant les concepts de bases (processus, bloc atomic) avant d'ajouter progressivement de nouvelles instructions du langage. Dans un premier temps, nous avions permis le compilateur de backtracker an d'avancer rapidement. Une fois la plupart du langage pris en compte, an d'avoir une grammaire LL, nous avons rétabli et dû refactorer une grande partie de la grammaire. Après cela, la grammaire étant considérée comme stable, nous avons pu attaquer sereinement la transformation. Par la suite, la grammaire n'a été modiée qu'à la marge pour résoudre quelques petits problèmes apparus lors de la construction de la transformation pml2spin. Quelques défauts mineurs ont aussi été notés et pourront être corrigés si une modication de moyenne envergure de la grammaire était à réaliser, an de ne pas modier pour des broutilles le code client (outline, togal). 3.1.2 Le choix d'une grammaire LL et ses conséquences Lors de la rédaction de la grammaire nous avons dû faire face à plusieurs choix, certains totalement anecdotiques, d'autres aux conséquences bien plus grandes. De loin, le choix d'avoir une grammaire LL fut le plus important. Pourquoi une grammaire LL? L'activation du backtracking (retour sur trace) lors du parsing va permettre d'écrire de manière bien plus simple, car ceci permet d'avoir une grammaire ambigüe. Face à un dilemme, le parseur optera pour une des options, et viendra essayer les suivantes si jamais celle-ci mène à une impasse. (Il s'agit de la même méthode utilisée dans prolog, appelée autrement méthode des essai et erreur.) L'écriture de la grammaire est simpliée, sans que la performance soit impactée de manière sensible. Par contre, ceci vient avec un coût: les erreurs de syntaxe seront mal localisées. Par conséquent, les messages d'erreur de syntaxe remontés à l'utilisateur seront assez cryptiques et risqueraient d'indiquer une mauvaise piste. C'est pour cela que la désactivation du backtracking, malgré les complexités impliquées par la rédaction d'une grammaire LL, est préférable. C'est d'ailleurs considéré comme une bonne pratique dans la communauté Xtext. 10

La grammaire xtext GAL comme inspiration Notre langage cible étant GAL, qui a aussi été développé utilisant le framework Xtext, nous nous en sommes inspirés an de faciliter la passe de traduction. Cependant, comme les deux langages sont assez diérents, nous n'avons pu réutiliser que les Expressions, et encore, de nombreuses modications ont dû être réalisées. En eet, Gal fait la distinction entre les expressions Booléennes et Entières, au niveau de sa grammaire, alors que pour promela, inspiré du C, il n'y a pas de distinction de ces deux genres d'expressions. Les deux ont été fusionnés dans la grammaire. Recursivité à gauche des expressions, et associativité des opérateurs. La nature intrinsèquement récursive des expressions a aussi dû être gérée. En eet, la plupart des expressions contiennent elles même d'autres expressions, et un grand nombre des règles de grammaire pour les expressions sont de la forme E = E <op> E, ce qui est assez problématique, surtout pour une grammaire LL. De plus, l'associativité des opérateurs doit être gérée. En eet le parseur doit savoir comment construire l'ast lorsqu'il y a deux opérations inxes de priorités diérentes. Par exemple a + b * c correspond à a + (b*c) et non (a+b)*c. Pour réaliser ceci en Xtext, nous allons dénir chaque règle de manière indépendante, mais chacune devra déclarer Expression comme son supertype. Surtout ses appels récursifs à ses sous-expressions, plutôt que de préciser la règle Expression, elle appellera la règle qui la suit dans l'ordre d'associativité. Ceci est illustré par ce fragment de grammaire: Or returns Expression: And ( {Or.left = current ' ' right = And)* ; And returns Expression: Not ( {And.left = current '&&' right = Not)* ; Not returns Expression: '!' {Not value = Comparison Comparison ; L'expression entre crochet correspond à une réecriture de l'arbre, c'est-à-dire que l'expression qui est retournée par l'appel à la règle And (le current), est aectée à l'attribut left du Or si jamais un token était rencontré. L'associativité doit aussi être gérée pour des opérateurs de même priorité. Par exemple, prenons une expression comme : a + b + c. En promela, l'associativité est gauche comme pour la plupart des langages, l'expression est donc interprétée comme (a + b) + c et évaluée de gauche à droite. Ceci est réalisé dans la règle xtext par la cardinalité * du bloc ( {And.left = current '&&' right = Not). S'il s'agissait d'une associativité droite, il aurait fallu utiliser la cardinalité? (1 au plus). Factorisation à gauche An d'avoir une grammaire LL, nous avons dû factoriser à gauche notre grammaire (left factoring). Ainsi, si deux règles commencent par le même pattern, celui-ci doit etre regroupé dans une règle à part. Ainsi, le parseur n'a pas à revenir en arrière, ou à choisir entre deux règles compatibles, ce qu'il ne peut pas faire sans aller voir plus en aval lequel est le bon. Il faut donc supprimer toute ambiguité pour le parseur. La left fractorisation a rendu la grammaire moins lisible. Ceci s'est surtout ressenti au niveau de certaines expressions, celles-ci pouvant toutes commencer par un token ID (c'est-à-dire une chaîne de caractères quelconque correspondant à un identiant). En pratique nous avons regroupé toutes ces instructions commençant par un token ID dans une règle spéciale pour plus de lisibilité. LLFactoredInstructions returns Instruction: //@ LLFactoring: Expression > Send, Receive, Assignement Expression ( {Send.channel = current (fifo?= '!' '!!') args = SendArgs {Receive.channel = current ( normal?= '?' '??' ) ( keep?= '<' args = ReceiveArgs '>' args = ReceiveArgs ) {Assignment.var = current kind = AssignmentOperators =>( newvalue = Expression )? {Condition.cond = current ) ; 11

Le nom entre crochets {Send permet de forcer la création d'un sous-type et ainsi, contrôler un peu mieux le Métamodèle qui sera déduit de la grammaire. Hierarchie des MetaClasses perturbée En plus de venir complexier les règles, la rédaction d'une grammaire LL en Xtext vient aussi perturber le metamodèle qui est déduit des règles de grammaire. En eet, comme on vient de le voir avec la factorisation gauche, la variable d'une Aectation ou le canal d'une Réception/Emission est une Expression, alors qu'on voudrait que ce soit une Reference. Quelques contrariétés du même type viennent perturber l'ast. De plus si l'on voulait que deux règles factorisées aient un super-type commun, il fallait dénir un certain nombre de règles factices pour cela. Il a été un temps envisagé de ger le ecore (désactiver la génération depuis la grammaire), et d'opérer les modications pour avoir les classes voulues. Cependant, ceci impliquait indirectement de ger la grammaire ce qui n'était pas envisageable à ce stade du développement. Finalement, nous avons simplié les choses en factorisant et regroupant tous les diérents types d'aectation, Send, Receive sous les mêmes classes et en utilisant des attributs pour encoder leur variabilité. Pour les Expressions à la place des variables, rien n'a pu être fait à ce niveau: une validation statique a été mise en place, et des fonctions utilitaires pour récupérer directement l'attribut sous le bon type. 3.2 Meta Modèle de Promela Le Méta Modèle nal est généré par Xtext dans le chier Promela.ecore à partir de l'ensemble des règles et annotations que l'on a mis en place dans la grammaire. Celui-ci est visualisable grâce au plug-in Eclipse Ecore Tools, qui va générer un tel diagramme de classe modiable. Montrer notre MétaModèle dans son intégralité n'aurait aucun sens. Tout simplement car un tel diagramme serait illisible de part la complexité du langage. Dans sa version complète, seule une navigation interactive aurait du sens. Pour avoir un aperçu nous avons donc préparé deux vues du MétaModèle à deux niveaux d'abstractions diérents pour lesquels nous avons réalisé des diagrammes lisibles. 3.2.1 Spécication Promela La première vue est celle d'ensemble, qui montre le lien entre les diérentes constructions du langage sans entrer dans la diversité des expressions et des instructions. Un code couleur a été utilisé pour départager des constructions de diérentes natures. ˆ En rouge, tout en haut, la Spécication Promela qui est la racine de notre arbre de syntaxe abstraite représentant tout programme Promela. ˆ En vert clair les Dénitions de processus, éventuellement nommées et dotées de paramètres. ˆ En bleu les Séquences et les Instructions qui vont décrire les actions entreprises par un processus. ˆ En blanc cassé, on trouvera les constructions reliées au typage. Il y a donc les types de bases, les structures dénies par les utilisateurs, ainsi que les "MTypes", c'est à dire des noms de messages an de pouvoir utiliser ACK SYNC comme valeur dans le programme ˆ En orange, les diérentes variables typées et macros du langage 12

3.2.2 Les Instructions Ce diagramme vient illustrer les principales instructions du langage Promela. Toute instruction fait partie d'une séquence, et certaines instructions contiennent une séquence donnant ainsi un structure récursive au langage que nous avons dû gérer pour la transformation. 13

3.2.3 Les Expressions Les expressions sont la catégorie sémantique avec la plus grande diversité de construction, dont la plupart sont de nature récursive(c'est-à-dire qu'elles contiennent elles même d'autres expressions). On y retrouve tous les opérateurs arithmétiques, booléens. Les principales feuilles des expressions sont les références à des variables, les constantes littérales et booléennes et certains opérateurs promela spéciques. Pour pouvoir gérer les références de structures et de tableaux, nous avons adopté une structure récursive inspirée du design pattern composite. Les Références (qui sont des expressions), sont soit une Référence de tableau, soit une référence de structure, ayant donc une référence associée à un index ou un nom de champs. Soit une "Atomic Reference" qui va se référer à une construction "Referable". Cette dernière est soit une déclaration de variable, soit une macro ou un symbole de message. Ceci est illustré dans le diagramme suivant: On retrouvera en bleu ciel les références, bleu foncé les élements référençables. 3.3 Limites du MM En suivant le précepte "Loose Grammar, Strict Validation", la grammaire seule accepte grand nombre de programmes qui ne sont pas du tout valides. Par exemple, si rien n'est fait pour vérier, le code suivant serait considéré comme correct: int c = 3; (4 + c) = 2 // Affectation Bidon En eet, que ce soit pour la variable d'une aectation, ou le canal d'une reception/émission, on ne peut malheuresement pas mettre une référence bien que c'est ce que l'on souhaiterait. Eectivement, pour éviter les forts appréciables erreurs error(211):../fr.lip6.move.promela.xtext/src-gen/fr/lip6/ [fatal] rule ruleidambiguous has non-ll(*) decision due to recursive rule invocations reachable from alts 2,4. Resolve by left-factoring or using syntactic predicates or using backtrack=true option., nous avons dû factoriser les règles comme préalablement raconté. De ce fait, ceux-ci sont des expressions, alors que seules les références sont acceptables! Pour autant, des vérications auraient dû être faites même si notre grammaire était bien plus stricte. En eet, une grammaire ne peut pas tout contenir, surtout avec un langage comprenant autant de constructions et un tel système de types. Une validation du programme et son modèle associé est donc nécessaire. En plus d'être inaccessible, une Grammaire stricte est bien plus complexe à écrire, beaucoup plus verbeuse et répétitive. Par exemple, si on avait voulu contraindre la présence des break uniquement dans des do au niveau grammatical, il aurait fallu pour cela dupliquer les règles Instructions, Step, Sequence par des règles soeurs [ISS]DansBoucle. Ce qui, de tout évidence, n'est pas une bonne pratique car étant dicile à maintenir en cas de modication et, de plus, propice aux erreurs. 14

4 Analyse Statique de Promela 4.1 Typage Le typage permet de vérier la concordance des types des expressions et des instructions : par exemple une variable de type short ne peut pas contenir une valeur de type int mais le contraire est possible. De même, nous ne pouvons pas recevoir ni envoyer n'importe quel type de message dans un canal de type déni. Cette vérication ne peut être faite que lors de la validation du programme. Elle doit aussi être étendue sur tous les types dénis dans Promela. Voici la solution que nous proposons : La stratégie que nous avons adoptée est de calculer d'abord les types dans la classe PromelaTypeProvider et de faire, ensuite, la validation des types dans PromelaTypeValidator. Nous avons représenté chaque type de Promela par une classe Java. Toutes ces classes Java implémentent l'interface PromelaType. La classe PBasicType est en fait une énumération qui regroupe tous les types primitifs (bit, bool, byte, short, int). A chacun est associé un nom (la chaîne de caractère du nom du type en question) et une taille(la taille en nombre de bits du type). Notre typage repose sur le fait qu'un type englobe tous ceux de taille inférieure. Dans Promela, nous avons l'ordre suivant: bit (1) < byte(8 bits) < short(16 bits) < int(32 bits) Les classes PArrayType, PChannelType et PUserType permettent de représenter, respectivement, les types tableau, channel et type utilisateur de Promela. Dans PromelaTypeProvider, nous allons retourner un type PromelaType pour chaque expression, variable et référence. Cela se fait par la surcharge d'une méthode typefor qui prends en argument chaque entité de la grammaire pour laquelle nous voulons récupérer un type. Nous utilisons un switch pour les cas simples. Pour les expressions pouvant être typées directement, on écrit donc le code suivant: def static dispatch PromelaType typefor(expression e) { switch (e) { True: PBasicType.BOOL //.. Others Comparison: PBasicType.BOOL //... Pour les expressions qui nécessitent plus de réexion, il s'agit d'adapter le typefor an qu'il renvoie le type eectif recherché. Dans l'exemple suivant, nous mettons en place le typefor pour les ChanVariable, c'est-à-dire les déclarations de canaux. Il convient dans un premier temps, an de pouvoir expliquer ensuite ce bout de code, d'évoquer la structure des canaux en Promela. Lorsque l'on déclare un canal, on lui donne les types des champs du message qu'il pourra contenir. Ainsi lorsque l'on déclare, par exemple, le canal suivant: chan qname = [ 8 ] of { int, short, byte on indique que ce canal peut contenir un message comprenant trois champs (un de type int, un de type short et un de type byte). Les messages sont donc des structures de données. Dans le code suivant, nous ajoutons dans l'ordre les diérents types des champs dans une liste. Ainsi, nous pourrons vérier ensuite qu'ils correspondent bien (et dans cet ordre) aux champs du message auquel on fait référence dans un send ou un receive. def static dispatch PChannelType typefor(chanvariable chan) { val size = (chan.initvalue.size as LiteralConstant).value; val varl = new ArrayList<PromelaType> for (Type t : chan.initvalue.types) { 15

if (t instanceof BasicType) { varl.add(pbasictype.get(t as BasicType)) else if (t instanceof StructTypeRef) { var name = (t as StructTypeRef).ref.name var struct = new HashMap<String, PromelaType>(); val f = (t as StructTypeRef).ref.champs for (StructField ty : f) { struct.put(ty.name, PBasicType.get(ty.type as BasicType)) varl.add(new PUserType(struct, name)) return new PChannelType(varL, size); Nous avons un validateur spécique pour le typage: PromelaTypeValidator.xtend, également rédigé en Xtend. Dans ce validateur, nous avons une méthode annotée par @Check pour chaque sorte d'expression excluant les expressions qui sont implicitement bien typées comme : les macros et les constantes. Nos validations peuvent être regroupées en deux catégories : validation des types des expressions et validation des types des instructions. Pour les expressions, nous procédons de manière récursive en typant chaque sous-expression qui les forment. Les instructions concernées par la validation que nous eectuons sont l'aectation, ainsi que l'émission et réception sur un canal (send et receive) La validation du typage de la règle de l'aectation consiste à récupérer le type de la variable référencée à gauche et le type de la nouvelle valeur assignée (l'expression à droite). On vérie ensuite si le type de l'expression est compatible avec celui de la variable Le send et le receive se ressemblent dans le sens que nous récupérons le type déni lors de la déclaration du canal auquel on fait référence, et vérie que le type des arguments (messages) correspond. Pour chaque cas où le typage n'est pas respecté, une erreur est signalée et un marqueur (et message associé) apparaît dans l'éditeur. 4.2 Validation Après l'élaboration de la grammaire, nous avons procédé à l'ajout de contraintes là où les règles de la grammaire était trop permissives ou ambigues. L'ajout de ces contraintes dans les règles de grammaire était dicile voire impossible, d'où la nécessité de mettre en place un validateur statique: PromelaValidator, rédigé en XTend. Ainsi nous gardons une grammaire propre, facile à manipuler et permissive, mais dotée d'une validation forte. Nous vérions donc que: ˆ les send, les receive, les poll se font sur des références à des canaux uniquement ˆ les aectations sont bien eectuées sur des références et que la nouvelle valeur assignée n'est pas nulle ˆ les blocs atomic contiennent uniquement des instructions ˆ les blocs déterministes ne contiennent pas de send ni de receive ( car ce ne sont pas des opérations atomiques, donc invalides dans ce cas) ˆ le nombre d'arguments d'un print est égal au nombre de valeurs attendues dans la chaîne de caractères (par l'intermédiaire de "%d", "%e","%c","%o","%u","%x") ˆ l'index de la référence à un tableau n'est pas négatif et ne dépasse pas la taille du tableau (pour la référence tab[i], on a bien i>=0 /\ i< tab.len) 16

Si une telle erreur est détectée, elle est signalée à l'utilisateur avec un marqueur et un message approprié. Nous pouvons également acher un avertissement commenté(warning) à l'utilisateur pour les cas qui n'entraînent pas d'erreur, mais qui peuvent être gênants, sont le signe d'une erreur de conception potentielle ou vont à l'encontre des conventions de style. Nous l'avons mis en place notamment pour: ˆ les séquences vides dans les alternatives, les boucles, les processus, les blocs atomic ˆ le cas où deux variables de même portée ont le même nom ˆ le nom d'une macro n'est pas en majuscule ˆ le cas où l'on trouve du code après un goto (ce code ne sera jamais exécuté, c'est donc du code mort, ou une erreur) ˆ le cas où l'on trouve des variables non utilisées ˆ le cas où les instructions break et skip ne se trouvent pas dans une boucle (en remontant dans les containers pères, on ne trouve pas de boucle) Dans ces cas-là, un quickx est proposé. Nous allons en parler plus en détail dans la partie suivante. La principale diculté rencontrée lors de l'élaboration du validateur était de naviguer sur les règles de la grammaire an de récupérer les entités à observer. Nous avons dû également d'abord élaborer une liste des endroits où la grammaire était permissive an de pouvoir mettre en place toutes les validations nécessaires. 5 Éditeur avancé Promela Bien que pouvant être amélioré davantage, l'éditeur Xtext généré par défaut s'avère déjà plus plaisant à utiliser et utile que le rudimentaire éditeur xspin. De plus certaines erreurs sont relevées à la volée ce qui n'est pas le cas avec les outils spin devant attendre la compilation du programme C généré. Nous avons décidé de personnaliser l'éditeur fourni par Xtext pour l'adapter au mieux possible aux besoins du langage Promela. Nous l'avons enrichi de diérentes manières: Ainsi, nous proposons des Quickxes, une outline plus esthétique et navigable, des templates et la possibilité de formatter le code. 5.1 Quickxes Comme expliqué dans la partie validation, nous nous sommes appuyés pour notre plugin sur une validation poussée des programmes Promela. Ainsi, nous avons également pris soin de donner la possibilité de traiter les erreurs envoyées par des quickxes. Comme vous pouvez le voir dans la capture d'écran ci-dessous, un quickx est proposé à l'utilisateur de l'éditeur pour la plupart des warnings et erreurs détectée. 17

Ainsi, la possibilité est oerte de: ˆ renommer une variable au nom dupliqué ˆ supprimer du code mort après un goto ˆ mettre les noms des Macro en majuscule ˆ supprimer les variables inutilisées ˆ ajouter un skip dans les corps vides (il est préférable d'avoir une instruction plutôt que de laisser vide une séquence) Les quickxes se trouvent dans le package quickfix dans le project de L'interface graphique fr.lip6.promela.xtext.ui. Le langage utilisé est xtend. La principale diculté rencontrée lors de leur élaboration était de récupérer ce qu'il fallait au niveau de la validation pour pouvoir ensuite le traiter simplement. 5.2 Outline and Labelling Pour permettre une meilleur expérience utilisateur, l'outline et labelling de base fourni par la première génération de code Xtext a été entièrement personnalisé pour être à la fois visuellement attractif et permettre une navigation dans le code optimale. L'outline correspond à une vue hiérachique des diérentes parties d'une code. Il s'agit juste d'une vie partielle de l'ast correspondant à la spécication en cours d'édition. Avec Xtend et ses switchs aux gardes typées, certaines parties du code sont quasi déclaratives, où on associe chaque construction du langage a une image et un résumé textuel. Rien de tel qu'une capture d'écran pour illustrer ceci. 5.3 Templates An de donner un coup de pouce au programmeur PROMELA et de rendre notre éditeur de texte plus engageant, nous avons décidé de proter des fonctionnalités oertes par Eclipse et de mettre en place des templates, comme ceux que l'ide propose pour d'autres langages. Ainsi, en un clic, l'utilisateur peut à présent récupérer le squelette pour un proctype, une boucle( for et do), une selection (if), un atomic ou un d_step. Ce service n'est pas proposé non plus, comme les précédents, par l'éditeur de l'outil SPIN. Les templates sont dénis dans le chier templates.xml, se trouvant dans le dossier templates du package 18

fr.lip6.move.promela.xtext.ui. Il s'agit d'un chier XML qui regroupe les templates que nous avons décidé de proposer. Chacun d'entre eux est déni dans un contexte précis et possède un identiant unique. On y dénit également la position du curseur après l'ajout du template en question. L'ajout du dossier templates dans les propriétés du build fait de sorte que les templates sont actifs par défaut au lancement de l'éditeur. Il n'y a donc plus besoin de les congurer dans les préférences. 5.4 Formatting Une autre fonctionnalité intéressante que nous proposons est le formattage du contenu du chier Promela. En appuyant simultanément sur les touches CTRL + SHIFT + F, l'utilisateur modie l'indentation et les sauts de ligne dans le programme pour le rendre plus clair et plus lisible. Voici les captures d'écran du programme test.pml avant et après le formatting: 19

Le formatting est déni dans le package fr.lip6.move.promela.xtext dans le package formatting des sources. Ce formateur est écrit en xtend dans un chier appelé PromelaFormatter.xtend. Il s'est agit de dénir les insertions de sauts de ligne, d'espace et autres caractères suivant les spécications de notre langage, mais aussi suivant la convention usuelle. 6 Transformation ToGal La réalisation d'une transformation spin vers gal a été l'aboutissement de notre projet. Nous présenterons, dans un premier temps, plus en détails la vocation d'une telle transformation avant de voir comment on a traduit les concepts promela vers gal. Ensuite, nous traiterons de l'architecture de notre traducteur et de la solution de visualisation graphique mise au point pour analyser les automates déduits des dénitions de processus promela. Pour nir nous reviendrons sur les résultats concrets que nous avons obtenus. 6.1 Objectif Le but ultime et donc de pouvoir traduire des spécications Promela vers une spécication GAL, que nous pourrons analyser avec l'outil ITS développé par le Lip6. L'intérêt de ceci est que ITS et SPIN utilisent deux paradigmes opposés de model checking avec leurs avantages respectifs selon les modèles. Spin se base sur une méthode explicite, alors qu'its se base sur une méthode symbolique qui peut s'avérer beaucoup plus performante et moins gourmande en mémoire. Développer une telle traduction, nous permettra de faire tourner la même spécication mais avec deux outils diérents et ainsi déterminer les méthodes les plus adaptées à un type de spécication précis, an d'utiliser dans 20

un second temps l'outil le plus adapté. Aussi, Promela étant un des langages de spécication de systèmes concurrents parmi les plus utilisés, ceci permet à l'outil ITS de toucher une plus large audience. 6.2 Mapping entre concepts Promela et Gal La première étape a été de voir comment traduire les concepts Promela vers ceux Gal avant de s'attaquer à l'implémentation de ces idées (et donc toutes les complications pratiques qui peuvent émerger). Comme nous l'avons vu en présentant le langage GAL, celui-ci ne contient que des concepts de très bas niveau, à savoir des variables, et des transitions. Il a donc fallu que nous voyions comment exprimer nos concepts d'assez haut niveau (processus, canal de communication, structures) avec ces constructions de base. Derrière sa syntaxe, Promela modélise des algorithmes de systèmes asynchrones distribués comme des automates non déterministes. Pour réaliser la convertion, un processus a été associé à une machine à état, c'est-à-dire à un ensemble d'états et de transitions. Pour ce faire nous avons recensé dans chaque processus l'ensemble des positions du pointeur de code, que nous avons représenté par un variable interne nommée PC (pour program counter à l'image de l'assembleur). La plupart des instructions promela correspondent à une action ayant lieu entre deux positions possibles du programme. Pour réaliser ceci en GAL, une variable d'état est associée à chaque processus, et contient sa position courante. Chaque instruction sera traduite vers une transition Gal. Cette transition sera notamment gardée par la valeur du PC (ainsi que d'éventuelles autres conditions d'exécutabilité). Cette transition contiendra la traduction de l'instruction en actions gal, et la dernière instruction sera la mise à jour du PC. La traduction des structures conditionnelles se fera vers autant de transitions que d'options, chacune étant gardée par la condition correspondante (en plus de la position courante du programme). Les goto et break correspondront eux à une simple mise à jour du PC. Tout ceci est capturée dans un objet ProcessRepresentation qui sera utiliser pour instancier plusieurs processus, mais aussi générer une représentation graphique de l'automate. Les variables et tableaux existant tous les deux dans les deux langages, la traduction est immédiate, il y a juste à s'assurer que les références vers une variable gal soient traduites en une référence vers la variable gal associée. Cette association sera maintenue dans une environnement de convertion. Les canaux de communication sont représentés à l'aide de trois variables GAL: une variable contenant le nombre d'éléments maximal du tableau, le nombre courant, et un tableau contenant les diérents messages transitant au moment considéré. Ce concept est capturé dans CanalRepresentation. Ainsi une émission dans un canal consiste à rajouter notre message à la position dont l'index est le nombre d'éléments courant, avant d'augmenter cette valeur. Une Réception sera implémentée en récupérant la valeur à l'index 0 avant de réécrire le tableau en décalant tous les éléments d'un cran vers la gauche et de diminuer le nombre de messages courant. Avec ce système un canal vide (respectivement plein) est détecté quand le nombre d'éléments courant est nul (égal au nombre maximum.) 6.3 Architecture Maintenant que nous avons annoncé comment se fait la traduction en principe d'un modèle promela vers gal, on va voir comment ceci est réalisé concrètement. L'opération de Traduction est gérée par une classe nommée PromelaToGALTranformer, dotée d'une méthode transformtogal qui prendra en entrée une PromelaSpecification et qui renverra une Specification gal. C'est cette méthode qui sera invoquée par l'action eclipse invoquable depuis l'interface graphique. Lors de la transformation, un Converter, un Environment et diverses représentations "TransfoTime" des concepts promela seront utilisés. Le Converter aura la charge de traduire les expressions et instructions, et l'environnement contiendra les liaisons entres les variables des programmes promela sources et gal cibles. A coté de cela, des classes utilitaires ont été introduites pour factoriser tout le code redondant. Nous allons désormais rentrer un peu plus en détail sur le contenu de ces diérentes classes. 6.3.1 Principales Classes 21

Actions Cette classe PromelaToGalAction est invoquée par Eclipse pour lancer la transformation. Cette classe étend la classe eclipse IObjectActionDelegate Elle contient un ensemble de chiers sur lesquels la transformation doit être réalisée. Cet ensemble de chier est mis à jour lorsque la sélection change à l'aide de la méthode redénie selectionchanged(iaction a, Iselection s) qui va ajouter tous les chiers promela (dont l'extension est.pml) à la liste des chiers à traiter. La méthode redénie run va, pour chaque chier, l'ouvrir, créer une représentation mémoire promela, réaliser la transformation, sauvegarder le modèles gal (sous forme brute, et sous forme "applatie") Transformer C'est la Classe qui va gérer la transformation de la spécication. Tout d'abord, elle va normaliser le modèle Promela et ainsi remplacer certains null par leur valeurs par défaut. Ceci nécessite un parcours complet de l'ast, du coup nous en protons pour récolter l'ensemble des instructions Run. Grace à cela, on pourra savoir combien de fois chaque dénition de processus sera instantiée. Après cela l'environnement et le converteur sont instantiées, ainsi qu'une Spécication Gal vierge Nous commençons par ajouter toutes les macros, dénitions de types et messages, et variables globales. Une fois ceci fait, une représentation transfo time va être créée pour chaque Run (création dynamique de processus), avant d'en créer une pour chaque dénition du processus. Quand toutes les ProcessRepresentation auront été créées, celles-ci seront instantiées le nombre de fois requis. Converter Le Converter contient toutes les méthodes de conversion d'instructions et expressions Promela vers GAL. Pour chaque instruction, il renverra une liste d'actions gal correspondantes, pour les expressions, il pourra les renvoyer soit sous la forme d'une Expression Booléenne soit Entière vu que la distinction existe en gal. Il existe aussi une méthode pour obtenir la garde d'une instruction (expression indiquant si l'instruction est exécutable). Cette classe contient une référence vers l'environnement pour pouvoir récupérer les références sur les variables gal. Environnement La gestion de l'environnement est assez complexe et a d'ailleurs tout un package dédié. Environment La classe façade Environement va contenir un environnement Local, et un Global. A la résolution des variables, celle-ci regardera dans un premier temps dans l'environnement local (à un processus), puis dans le global en cas d'échec. Deux méthodes permettent de mettre en place un nouvel environnement local, ou de délier celui actuel. Ces méthodes seront invoquées au début et à la n de l'instantiation de chaque processus. Pour résumer, cette classe capture le mapping entre les variables Promela, et les variables GAL. Local/GlobalEnvironment La classe LocalEnvironment représente un environnement local. Il contient les associations pour les variables simples (qu'on a appelé atomic), les tableaux et canaux vers leur représentation gal. Ces trois sont stockées dans 3 maps diérents. A cela s'ajoute les méthodes pour ajouter une nouvelle liaison, ou récupérer la variable gal associée à celle promela. Pour nir, une méthode sert à rajouter les déclarations qu'elle contient dans la spécication gal. La classe GlobalEnvironment étend la version locale en y rajoutant les attributs méthodes associées aux macros et symboles de message. Il s'agit juste d'une Map personnalisée. EnvironmentAdapter Cette classe sert à créer les environnements, à bien les peupler. L'environnement contient juste les liaisons, cette classe va se charger pour chaque variable promela de créer celle gal qui y sera associée. Pour chaque type de variables (MemVar, Channel, Macro, Mtype), une méthode handle va se charger de créer l'équivalent gal, et d'associer les deux dans l'environnement. En réalité, il s'agit d'une classe abstraite. En eet, deux classes statiques internes viennent raner la classe pour distinguer la création de l'environnement Global, et local. Ces deux classes ranent une méthode makename qui va déterminer le nom de chaque variable. Ceci permet de préxer les variables locales du nom de leur processus pour gérer la portée et éviter tout conit de nom dans le gal généré. De plus la version locale va surcharger 22

les méthodes qui ne concernent que le Global pour lever une exception si jamais elles étaient invoquées. 6.3.2 Classes Représentation "Runtime" Ces classes ont été créées an de capturer une représentation de nos objets promela qui va contenir les diérents éléments GAL qui vont réaliser ces concepts. En plus de contenir dans un objet unique ces diérentes données, des méthodes ont été produites pour directement produire les gardes ou actions que l'on associera aux instructions. ProcessRepresentation On peut considérer ProcessRepresentation comme classe principale de la transformation, celle qui contient l'essentiel de la logique de traduction. C'est dans cette classe, qui contient la représentation sous forme d'automate de processus, qu'on trouve tant les méthodes de fabrique statique qui va créer la représentation à partir d'une ProcessDefinition, que la méthode pour instancier cette représentation dans une spécication GAL. Classes Internes Pour la réalisation, plusieurs classes internes ont étés développées. On a tout d'abord la classe PC, et ses ranements PCid et PClabel qui vont représenter les positions possibles dans le code. Le PClabel sert à gérer les références vers un certain label dans le cadre du goto, et a été introduite car le vrai PCid associé au Label n'a peut être pas encore été résolu. Les Ptransitions (avec P pour promela, et pour éviter une ambiguité avec les transitions gal, vers lesquels elles seront traduites), correspondent à une instruction promela comprise entre deux positions dans le code. Une éventuelle garde (condition) peut y être associée. Création d'une représentation Voici l'esprit de la procédure pour créer une ProcessRepresentation. Tout d'abord les déclarations de variables sont collectées lors d'une première passe. Ensuite un PC initial est créé, puis chaque instruction du bloc va être traitée par une méthode process. Cette méthode récursive va, selon le type de l'instruction, créer une transition correspondante (ex: assignment, send, receive), ou par exemple s'appeler récursivement sur ses sous instructions dans le cas d'une séquence. Les Iterations (do), et alternatives (if) vont elles aboutir à la naissance de plusieurs transitions. Diverses méthodes vont permettre de factoriser certains traitement, ainsi on trouvera les méthodes privée processopt, processelseopt, processgoto, processbreak, processintrlist Un Système a été mis au point pour pouvoir gérer les valeur de PC. En résumé, un nouveau Pc est créé sauf si un PC nal a été fourni à l'invocation de la méthode process. Ceci est notamment utilisé quand on traite une des options de la boucle, on sait que le dernier élément doit renvoyer à la position correspondant au début de la boucle. Une fois toutes les instructions traitées, et donc les transitions collectées, une normalisation nale va se charger de remplacer tous les PClabel par le PC cible qui est désormais connu. Instantiation Cette méthode va créer les variables et transitions représentant le processus promela dans la spécication gal qui lui sera passée. La méthode commence par créer une variable d'état, qui contiendra la valeur du pc courant. Ensuite un environnement local sera créé à l'aide d'un Adaptateur Local, et attaché à l'environnement du converter. Chaque transition sera ensuite instantiée. Celle-ci sera gardée par une éventuelle condition à laquelle s'ajoutera la vérication que la valeur de l'état courante est la bonne; et une action de mise à jour du pc est ajoutée en n de transition. A noter qu'un eort particulier a été fait pour commenter les diérentes variables et expliquer leur vocation comme on peut le constater avec les exemples de codes générés disponnibles en annexe. Une variante de la méthode instantiate avec un ag inactive existe pour gérer les processus qui ne sont pas initialement activés, et qui le seront une fois le run correspondant rencontré. Autres D'autres méthodes existent: 23

ˆ Création représentation graphique, avec la méthode todot, ce qui sera décrit plus en détail ultérieurement. ˆ une création et représentation de processus à la volée createinitprocess qui sert uniquement pour les dénitions de processus init qui sont uniques. Channel Representation Comme cela a été décrit dans l'association entre les concepts des deux langages, cette représentation contient une référence sur les 3 variables évoquées. A cela s'ajoute un ensemble de méthodes pour générer les opérations sur les canaux, Send, Receive, Pool, ainsi que le gardes correspondantes. Run Representation Les Runs, c'est-à-dire l'activation dynamique de processus, n'étaient pas gérés dans les premières versions de notre transformation. Ils ont cependant été introduits pour supporter l'ensemble des chiers du benchmark beem. La représentation contient la variable d'état correspondante à l'état, ainsi qu'une méthode pour mettre celui-ci à jour. Celle-ci devra être revue quand les paramètres de processus seront intégrés. UserType/StructRepresentation Les Structures ne sont pas encore supportées. Cette classe aura pour vocation de représenter une instance de structure lors de la phase de traduction. L'information sera contenue dans un map entre les noms des diérents champs, et les variables gal associées(ou éventuellement vers une autre représentation abstraite de structure en cas de structure imbriquée). Des méthodes permettront de récupérer la variable gal ciblée à partir d'une StructRéférence. 6.3.3 Classes utilitaires. GALUtils Cette classe est une collection de fabriques statiques permettant d'obtenir un objet GAL correctement initialisé. En eet, ceci était nécessaire vu que la Factory EMF à notre disposition nous renvoie des objets avec leurs propriétés non initialisées. Par exemple, la méthode public static IntExpression makegalint(int i) va se charger de créer un entier gal à partir d'une valeur int en créant les objets nécessaire, et en réglant leurs attributs aux bonnes valeurs. Cette fonction est un peu plus complexe qu'en apparence car il n'y a pas de constantes de valeurs négatives en Gal. Si l'entier demandé est négatif, il faut donc créer une constante avec sa valeur absolu, et l'enrober dans une UnaryMinus. D'autres méthodes permettent de créer les références à une Variable à partir de la Variable, ou de combiner avec des And, ou Or deux ou plusieurs expressions booléennes. PromelaUtils Cette classes contient grand nombre de méthodes utilitaires. On y trouve l'équivalent Gal des fabriques, mais pour les constructions promela. De plus, c'est ici que l'on trouve les méthodes utilitaires pour récupérer les références des Assignments, Send, Receive, comme évoqué dans la partie grammaire. Une méthode asinstruction(step) va aussi factoriser la vérication du typage, et le cast des Step vers les Instructions (les steps sont soit des instructions, soit des déclarations de variables, ou déclarations d'accès exclusifs aux canaux). TransfoUtil Cette classe sert à factoriser la levées des exceptions lors de la conversion pour avertir de données illégales, invalides, ou de constructions du langage non encore soutenues. Ceci permet de pourvoir changer en un seul lieu le type d'exception envoyées (Pour l'instant une UnsupportedOperationException, qui est une RuntimeException), et le message associé. Ces méthodes sont importées de manières statiques par le converter et les autres classes l'utilisant et les exceptions sont levées de la manière suivante: throw illegal("this Rus as already been handled") ou throw unsupported("struct are not supported for now") 24

6.4 Visualisation du Graphe de ot de contrôle 6.4.1 Motivation An d'avoir une meilleur vue des résultats de notre transformation et de la représentation des processus que l'on avait mise au point, nous avons mis un processus de génération de graphes qui s'est avéré grandement utilisé pour l'analyse de nos résultats et le débugage. En eet, ceci était indispensable. Le code Gal produit est une présentation textuelle et aplatie. La structure ne saute pas au yeux, malgré l'eort apporté pour que la vocation des variables soit clairement identiée et le code commenté. Une description graphique a donc été développée en utilisant le langage Dot, et l'outil graphviz. 6.4.2 Choix Technique Dot a été choisi pour de nombreuses raisons au delà de l'expérience préalable. Ce langage plus très jeune mais super ecace est un des standards pour décrire des graphes et les outils associés sont open-sources. Une fois ceux-ci décrits dans une syntaxe de base très simple, un outil comme dot ou neato viendra générer une image après avoir agencé le graphe selon un algorithme de layout particulier. Dot permet donc de produire rapidement une visualisation facilement personnalisable. 6.4.3 Génération de représentation textuelle Pour obtenir nos graphes de ot de contrôle il a donc fallu générer une description de graphe au format dot à partir de nos ProcessRepresentation. La classe possédait déjà toutes les informations nécéssaires pour générer la représentation textuelle du graph. Dans le graphe, les noeuds/node vont correspondre aux PCs, donc positions possibles dans le code et les arrows/edge vont correspondre au diérentes transitions. Pour la génération, trois méthodes todot on donc été introduites: ˆ au niveau des PC an de générer la description du noeud correspondant. Celui-ci sera personnalisé selon ces propriétés (en eet les noeuds correspondant à des labels, ou des entrées de boucle ont une forme et couleur particulières. ˆ au niveau des PTransition pour décrire l'edge correspondant. ˆ la principale dans ProcessRepresentation qui va se charger d'invoquer la méthode todot sur l'ensemble des PC et PTransition. De plus, un marquage de certain etat à l'aide d'une enum PCTAG a été utilisé pour décorrer de manière particulières les états correspondant à un label, ou l'entrée dans un do ou if 6.4.4 Action, intégration plugin Une action pour produire les graphes a donc été introduite dans le plugin. Celle-ci va générer les diérentes descriptions dot correspondante aux diérentes dénitions de processus. Ceux-ci seront ensuite sauvegardés sur le disque, avant qu'une image au format svg et png ne soient générés si l'outil dot est installé. Tout ceci est déclenchable de la même manière que la transformation Gal. 6.4.5 Améliorations envisageables Cette première version s'est déjà montrée d'une très grande valeur, mais on a tous les éléments pour pouvoir faire quelque chose de bien plus utile et pratique à utiliser. En eet, il serait envisageable de développer une vue eclipse qui permettrait de voir à la volée les automates associées aux dénitions de processus du programme courant. De la même manière, un build continue qui reproduirait les graphes au fur et à mesure, comme des chiers dérivés/compilés peut s'avérer très pratique pour l'utilisateur. Tout ce qu'il faut est présent, il sut juste d'invoquer, combiner les fonctions et développer un frontend pour rajouter ces fonctionnalités. 25

On pourrait aussi envisager d'orir une autre représentation du graphe de ot de contrôle en optant pour un graphe bipartites. Ceci nous permettrait d'avoir des descriptions plus précises des transitions en y faisant apparaître à la fois les actions et la garde associée à celles-ci. La représentation actuelle quant a elle pourrait être améliorer en faisant apparaître l'imbrication des séquences, en les regroupant dans des sous-graphes dot. Pour nir, la possibilité de customizer les couleurs, choisir le format d'image, pourrait être oerte à l'utilisateur en construisant une page eclipse de préférence à l'image de ce qu'il existe déjà dans le plug-in ITS. 6.5 Résultats. 6.5.1 La base de Données Beem An d'évaluer les résultats de nos transformations, nous avons utilisé les modèles du jeu de test de la base de données BEEM. Cette base de données est une collection de modèles (dont la vocation est de doter le domaine du model checking d'exemples standards an de comparer les diérentes approches. Elle a été établie par un groupe de recherche de l'université de Brno, en République Tchèque, mais leurs travaux ont été interrompus. Il y a en tout 57 modèles regroupés en 8 groupes (protocoles de communication, primitives de synchronisation, élections de leader, planication, etc). Chaque modèle possède plusieurs, plus ou moins importantes, comme le fameux repas des philosophes selon le nombre de convives. Les résultats de l'outil spin sont disponible à l'adresse suivante: http://spinroot.com/spin/beem.html et nous ont servis de base de comparaison. 6.5.2 Nos résultats Notre transformation ne permet pas encore de gérer l'ensemble des modèles, mais un nombre conséquent de modèles est déjà géré et la démarche peut déjà être qualiée de concluante. Nous gérons actuellement 30% des chiers de la base beem, et nos résultats actuels sont consultables en annexe. Sur nos chiers gal générés, nous avons fait tourner l'outil de model checking its-reach et voici les premières conclusions. (l'ensemble des résultat est consultable en annexe) Les résultats sont très concluants, et les performances souvent supérieures à promela. Nous avons même réussi à gérer des modèles non pris en charges par promela, notamment les modèles phils7 et 8 où spin ne peut suivre l'explosion exponentielle du nombre d'états. Le modèle du dîner des philosophes (dont une sample de code est disponible en annexe) donne de meilleur bien meilleurs résultats en lors d'une analyse model checking basée sur les méthodes symboliques. Par exemple malgré le fait que les premiers tests aient été réalisés sur un modeste netbook, les résultats sont saisissants. Par exemple, le repas avec 16 convives aura été traité en moins d'une seconde à l'aide d' its sur le gal que nous avons généré alors que celui-ci n'est pas géré par spin et divine qui respectivement mettent 359 et 3840.4 secondes (6 et 64 minutes) (sans toutefois arriver au bout de l'énumération). On peut voir dans ce tableau les résultats respectifs des 3 outils (its-reach sur nos gal générés, et beem sur modèle divine, et spin sur promela) Model Nb Convives #S Mem(kb) Time Gal T. Spin T. Beem phils 1 4 80 2776 0.02 0 0.4 phils 2 5 581 2844 0.04 0 0.4 phils 3 6 729 2808 0.02 0 0.4 phils 4 9 340789 3092 0.26 2.72 9.5 phils 5 12 531440 2924 0.1 4.26 13.9 phils 6 15 1.43489 (+07) 3144 0.16 144 589.7 phils 7 13* 7.19348 (+07) 3428 0.32 568 3965.6 phils 8 16 4.30467 (+07) 3112 0.16 359 3840.4 Phils 7 est une variante avec un compteur. 26

Cependant sur d'autres chiers la diérences et moins agrantes, et sur certains modèles les méthodes symboliques sur les gal générés sont moins performantes que spin sur le promela original. Ceci semble bien conrmer les résultats de l'étude LTSMIN: Distributed and Symbolic Reachability par S Blom qui avait mis en évidence la complémentarités des deux approches, les méthodes explicites marchant mieux sur des modèles au nombres d'états réduit. 27

7 Conclusion 7.1 Bilan du projet En conclusion, nous pouvons armer que nous avons atteint les objectifs xés, même si de nombreuses améliorations peuvent être apportées au fruit de notre travail (nous en parlerons plus en détails dans la partie Perspectives, consacrée à cet eet). Nous avons développé une grammaire et un métamodèle pour le langage Promela. Parallèlement, nous avons développé les méthodes pour vérier les programmes promela avec une analyse de typage et une validation. Pour nir, nous avons réalisé l'objectif nal du projet, la transformation d'une spécication Promela vers le formalisme GAL. Ce faisant, notre projet est assorti d'un éditeur xtext eclipse, personnalisé et enrichi de nouvelles fonctionnalités. 7.2 Bilans Personnels 7.2.1 Adrien Ce projet STL a été l'occasion de travailler sur un projet d'envergure. Il m'a permit de découvrir plusieurs "technos", principalement celles associées au framework Xtext, et au développement de plugin Eclipse, mais aussi de perfectionner mes compétences dans certaines autres connaissais déjà, notamment dot et Java. J'ai aussi pu utiliser en pratiques les connaissances acquises cette année, je pense notamment aux cours orienté langage et génie logiciel à savoir ILP, APS et IL (respectivement Implantation Langages de Programmation, Analyse des Programmes et Sémantique et Ingénierie Logicielle). Je tenais aussi à remercier Yann Thierry-Mieg notre encadrant et commanditaire pour ce qu'il m'a appris ce semestre tant en terme de connaissances théoriques et techniques que de méthodologies. Ce projet fut donc globalement une expérience très enrichissante et formatrice à de nombreux égard. 7.2.2 Fjorilda Ce projet m'a tout d'abord attiré par son côté technique. En eet, les technologies qu'on y a abordées (à savoir: XText, Xtend, Promela, GAL) m'étaient inconnues, et, j'ai pu les découvrir et les utiliser dans un projet d'envergure. Bien que ce projet ait l'air abstrait au premier abord, il s'est avéré beaucoup plus concret dans sa nalité. Eectivement, Eclipse est un outil que j'utilise depuis longtemps et régulièrement, participer au développement d'un plug-in pour cet IDE m'a permis de connaître plus en profondeur son fonctionnement. D'autre part, savoir que ce projet serait utilisé par la suite, m'a beaucoup motivé. De plus, je peux ajouter que l'élaboration d'une grammaire m'a permis de mettre en pratique les connaissances en sémantique acquises lors de l'ue APS. En conclusion, je peux armer que j'ai acquéri de nouvelles compétences et que je suis satisfaite de la contribution réalisée par notre groupe. 7.2.3 Julia Ce projet de STL fut pour moi l'occasion d'aborder des technologies auxquelles je n'ai jamais eu à faire auparavant. En eet, j'ai choisi ce projet dans cette perspective d'autant plus que travailler plus en profondeur sur la grammaire d'un langage de programmation m'intéressait vraiment. Par le passé, je n'ai que très peu eu l'occasion de me pencher sur de telles problématiques, si ce n'est dans quelques enseignements en licence tels que la Théorie des Langages, mais ce n'était que très superciel. Toutefois, cette année, j'ai pu en apprendre davantage, et d'un autre point de vue, dans le module APS et pu mettre cela en pratique. J'ai pu également découvrir comment se passait le développement d'un plugin Eclipse et approfondir la façon dont j'utilisais cet IDE jusqu'alors. Je suis satisfaite du travail que nous avons fourni et du résultat obtenu. 28

7.3 Perspectives Les bases ont été posées, mais de nombreuses fonctionnalités, plus ou moins diciles à mettre en place, peuvent être ajoutées au travail existant. Ce perspectives peuvent se faire selon les trois axes que nous allons à présent aborder. 7.3.1 Support de nouvelles constructions du langage Promela. Le langage Promela ayant été enrichi dans ses dernières versions, le support des nouvelles constructions de ce langage pourrait être mis en place. En eet, l'on pourrait supporter des constructions telles que le LTL (Linear Temporal Logic). De plus, Promela permet l'ajout de code C dans le programme, il serait donc possible de faire en sorte que ceci ne soit pas considéré comme une erreur syntaxique, au moins au niveau de l'éditeur. Il faut aussi ajouter que la traduction vers GAL ne supporte pas encore toutes les constructions: nous nous sommes concentrés sur les constructions les moins exotiques, an de supporter tout le banc de test Beem, laissant de coté certaines d'entre elles. Par exemple: les canaux multitypes, les réceptions aléatoires, les structures, ou les paramètres de processus. Certains d'entre eux ont déjà été ébauchés et aucun ne devrait demander de modication majeure qui nécessiterait une refonte de l'architecture déjà conçue. En ce qui concerne les structures, nous pouvons procéder de deux manières: soit faire une deuxième transformation Promela to Promela pour les applatir en diérentes variables, soit créer une StructureRepresentation pour lier l'identiant de la structure vers les variables en GAL. Actuellement, les blocs atomic sont considérés comme un d step dans la transformation. Il faudrait donc permettre à un atomic de s'interrompre au milieu quand il contient une instruction bloquante. Nous avons rééchi à une solution, mais celle-ci apporterait des changements conséquents dans la transformation. 7.3.2 Perfectionnement de l'éditeur L'éditeur Promela que nous avons déjà bien amélioré pourrait l'être d'avantage encore. En eet, nous pourrions revoir le formattage pour quelques points, comme rajouter des espaces/retour à la ligne où cela rendrait le code plus lisible (après chaque instruction conséquente par exemple, pour aérer le texte). D'autres quickxes pourraient être développés en se basant sur les erreurs les plus fréquentes. Par exemple, proposer la déclaration d'une variable lorsque l'on fait appel à la référence d'une variable qui n'existe pas encore. L'indication du typage au survol des entités pourrait également mis en place et serait une fonctionnalité intéressante. La coloration syntaxique par défaut peut aussi être changée pour rajouter à l'esthétique du code et à sa lisibilité. Celle-ci permettrait par exemple de mieux distinguer les structures de contrôles, les goto, l'indication des types, les canaux des variables mémoire, etc. Une amélioration du système d'auto-complétion pourrait également être mise en place. 7.3.3 Intégration, et nouvelles fonctionnalités du plugin togal Le plugin togal pourrait encore être amélioré pour apporter à l'utilisateur encore plus de fonctionnalités. Une vue eclipse pourrait être développée pour que le graphe de ux de contrôle puissent être directement visualisé. Il est également envisageable que la génération du code Gal, ainsi que celle des graphes automates de processus, se fasse en arrière plan lors de la transformation. Une page de conguration du plug-in pourrait aussi être mise au point avec la possibilité de congurer différentes options tel le style graphique des automates, le nom du chier généré, ou autres ayant plus à trait au chier gal généré. Le plug-in mériterait aussi d'être refactoré an de passer à la nouvelle architecture eclipse en dissociant les actions en une commandes et de multiples handlers, ce qui rendrait plus exible la manière d'invoquer la transformation, actuellement liée au menu déroulant. Un standalone invocable depuis la ligne de commande serait aussi des plus appropriés. 29

8 Annexes 8.1 Plugins Spin2Gal Notre Editeur Promela ainsi que le module de transformation spin2gal pour convertir les modèles promela vers gal sont disponibles danc eclipse, dans le menu Help > Install New Software en renseignant l'update site suivant: https://teamcity-systeme.lip6.fr/guestauth/repository/download/pstl_spin/.lastsuccessful/ update-site 8.2 Exemples de Transformation Voici deux exemples de la transformation que notre outil spin2gal permet de réaliser. Pour chacun des modèles, on montrera la spécication Promela originale, la spécication Gal générée ainsi qu'une représentation sous forme graphique de l'automate associé au processus. 8.2.1 Simple compteur Ce modèle décrit un simple compteur. Code Promela original #define MAX 42 int cpt; // Simple compteur active[1] proctype inc() { do ::(cpt<max)-> cpt++ ::else-> break od; Code GAL Produit gal firstsample_flat { int cpt = 0 ; /** @pcvar process inc_0 */ int inc_0_pcvar_ = 0 ; /** @proctrans inc_0 0 -> 1 : Break */ transition inc_0 t0 from_0_to_1 [inc_0_pcvar_ == 0 &&! cpt < 42] { /** @PCUpdate 1 */ inc_0_pcvar_ = 1 ; /** @proctrans inc_0 0 -> 0 : Assignment */ transition inc_0 t1 from_0_to_0 [inc_0_pcvar_ == 0 && cpt < 42] { /** Assignment */ cpt = 1 + cpt ; /** @PCUpdate 0 */ inc_0_pcvar_ = 0 ; Illustration du Flot de Contrôle 30

Resultat Code dot Voici le code source du graphe. // Representation du processus inc digraph inc { // Liste des transitions PC_0 -> PC_1 [ label = "Break" ]; PC_0 -> PC_0 [ label = "Assignment" ]; // Liste des etats PC_0[ label = "Pc:0", style = "filled", fillcolor = "palegreen:spinggreen", shape = "tripleoctagon"] PC_1[ label = "Pc:1"] 8.2.2 YAPE: Yet Another Philospher Example Cet example se base sur le "Oh combien classique" diner des philosophes de Dijkstra. Code Promela original byte fork[4]; active proctype phil_0() { think: if :: d_step {fork[0]==0;fork[0] = 1; goto one; fi; one: if :: d_step {fork[1]==0;fork[1] = 1; goto eat; fi; eat: if :: fork[0] = 0; goto finish; fi; finish: if :: fork[1] = 0; goto think; fi; active proctype phil_1() { think: if :: d_step {fork[1]==0;fork[1] = 1; goto one; fi; one: if :: d_step {fork[2]==0;fork[2] = 1; goto eat; fi; eat: if :: fork[1] = 0; goto finish; fi; finish: if :: fork[2] = 0; goto think; fi; 31

active proctype phil_2() { think: if :: d_step {fork[2]==0;fork[2] = 1; goto one; fi; one: if :: d_step {fork[3]==0;fork[3] = 1; goto eat; fi; eat: if :: fork[2] = 0; goto finish; fi; finish: if :: fork[3] = 0; goto think; fi; active proctype phil_3() { think: if :: d_step {fork[3]==0;fork[3] = 1; goto one; fi; one: if :: d_step {fork[0]==0;fork[0] = 1; goto eat; fi; eat: if :: fork[3] = 0; goto finish; fi; finish: if :: fork[0] = 0; goto think; fi; Code GAL Produit gal phils_1_flat { /** @pcvar process phil_0_0 */ int phil_0_0_pcvar_ = 0 ; /** @pcvar process phil_1_0 */ int phil_1_0_pcvar_ = 0 ; /** @pcvar process phil_2_0 */ int phil_2_0_pcvar_ = 0 ; /** @pcvar process phil_3_0 */ int phil_3_0_pcvar_ = 0 ; array [4] fork = (0, 0, 0, 0) ; /** @proctrans phil_0_0 5 -> 0 : Assignment */ transition phil_0_0 t0 from_5_to_0 [phil_0_0_pcvar_ == 5] { /** Assignment */ fork [1] = 0 ; /** @PCUpdate 0 */ phil_0_0_pcvar_ = 0 ; /** @proctrans phil_0_0 1 -> 3 : Atomic */ transition phil_0_0 t1 from_1_to_3 [phil_0_0_pcvar_ == 1 && fork [1] == 0] { /** Première instruction de l'atomic*/ fork [1] = 1 ; /** @PCUpdate 3 */ phil_0_0_pcvar_ = 3 ; /** @proctrans phil_0_0 0 -> 1 : Atomic */ transition phil_0_0 t2 from_0_to_1 [phil_0_0_pcvar_ == 0 && fork [0] == 0] { /** Première instruction de l'atomic*/ fork [0] = 1 ; /** @PCUpdate 1 */ phil_0_0_pcvar_ = 1 ; /** @proctrans phil_0_0 3 -> 5 : Assignment */ transition phil_0_0 t3 from_3_to_5 [phil_0_0_pcvar_ == 3] { /** Assignment */ fork [0] = 0 ; /** @PCUpdate 5 */ phil_0_0_pcvar_ = 5 ; /** @proctrans phil_1_0 0 -> 1 : Atomic */ transition phil_1_0 t0 from_0_to_1 [phil_1_0_pcvar_ == 0 && fork [1] == 0] { /** Première instruction de l'atomic*/ fork [1] = 1 ; /** @PCUpdate 1 */ phil_1_0_pcvar_ = 1 ; 32

/** @proctrans phil_1_0 3 -> 5 : Assignment */ transition phil_1_0 t1 from_3_to_5 [phil_1_0_pcvar_ == 3] { /** Assignment */ fork [1] = 0 ; /** @PCUpdate 5 */ phil_1_0_pcvar_ = 5 ; /** @proctrans phil_1_0 1 -> 3 : Atomic */ transition phil_1_0 t2 from_1_to_3 [phil_1_0_pcvar_ == 1 && fork [2] == 0] { /** Première instruction de l'atomic*/ fork [2] = 1 ; /** @PCUpdate 3 */ phil_1_0_pcvar_ = 3 ; /** @proctrans phil_1_0 5 -> 0 : Assignment */ transition phil_1_0 t3 from_5_to_0 [phil_1_0_pcvar_ == 5] { /** Assignment */ fork [2] = 0 ; /** @PCUpdate 0 */ phil_1_0_pcvar_ = 0 ; /** @proctrans phil_2_0 1 -> 3 : Atomic */ transition phil_2_0 t0 from_1_to_3 [phil_2_0_pcvar_ == 1 && fork [3] == 0] { /** Première instruction de l'atomic*/ fork [3] = 1 ; /** @PCUpdate 3 */ phil_2_0_pcvar_ = 3 ; /** @proctrans phil_2_0 5 -> 0 : Assignment */ transition phil_2_0 t1 from_5_to_0 [phil_2_0_pcvar_ == 5] { /** Assignment */ fork [3] = 0 ; /** @PCUpdate 0 */ phil_2_0_pcvar_ = 0 ; /** @proctrans phil_2_0 0 -> 1 : Atomic */ transition phil_2_0 t2 from_0_to_1 [phil_2_0_pcvar_ == 0 && fork [2] == 0] { /** Première instruction de l'atomic*/ fork [2] = 1 ; /** @PCUpdate 1 */ phil_2_0_pcvar_ = 1 ; /** @proctrans phil_2_0 3 -> 5 : Assignment */ transition phil_2_0 t3 from_3_to_5 [phil_2_0_pcvar_ == 3] { /** Assignment */ fork [2] = 0 ; /** @PCUpdate 5 */ phil_2_0_pcvar_ = 5 ; /** @proctrans phil_3_0 3 -> 5 : Assignment */ transition phil_3_0 t0 from_3_to_5 [phil_3_0_pcvar_ == 3] { /** Assignment */ fork [3] = 0 ; /** @PCUpdate 5 */ phil_3_0_pcvar_ = 5 ; /** @proctrans phil_3_0 0 -> 1 : Atomic */ transition phil_3_0 t1 from_0_to_1 [phil_3_0_pcvar_ == 0 && fork [3] == 0] { /** Première instruction de l'atomic*/ fork [3] = 1 ; /** @PCUpdate 1 */ phil_3_0_pcvar_ = 1 ; /** @proctrans phil_3_0 5 -> 0 : Assignment */ transition phil_3_0 t2 from_5_to_0 [phil_3_0_pcvar_ == 5] { /** Assignment */ fork [0] = 0 ; /** @PCUpdate 0 */ phil_3_0_pcvar_ = 0 ; /** @proctrans phil_3_0 1 -> 3 : Atomic */ transition phil_3_0 t3 from_1_to_3 [phil_3_0_pcvar_ == 1 && fork [0] == 0] { /** Première instruction de l'atomic*/ fork [0] = 1 ; /** @PCUpdate 3 */ phil_3_0_pcvar_ = 3 ; 33

Illustration du Flot de Contrôle 8.3 Résultats Benchmark Beem Actuellement 86 sur 252 sont gérés. Voici les résultats sur ces chiers: Conti Model #S Time Mem(kb) n. SDD n. DDD peak SDD peak DDD SDD Hom DDD Hom adding 1 7372 0.1 3868 2 243 5 9092 6 33 adding 2 836838 19.3 176544 2 2554 5 452350 6 33 adding 3 1.89438 (+06) 48.56 427964 2 3841 5 921842 6 33 at 1 39356 0.24 6032 2 1071 5 27170 6 211 at 2 49445 0.3 7292 2 1261 5 36929 6 211 at 3 1.71162 (+06) 3.2 41292 2 4619 5 314443 6 276 at 4 6.59725 (+06) 5.26 70908 2 8347 5 583029 6 341 at 5 3.19994 (+07) 14.94 165552 2 18185 5 1.34688 (+06) 6 341 at 6 1.6059 (+08) 57.68 612980 2 51222 5 4.92618 (+06) 6 341 at 7 8.19244 (+08) 64.98 707544 2 38175 5 6.51877 (+06) 6 406 bakery 1 1506 0.04 3216 2 350 5 4486 6 83 bakery 2 1146 0.04 3032 2 214 5 2945 6 83 bakery 3 32919 0.32 7508 2 2835 5 37835 6 123 bakery 4 157003 1.16 18368 2 7157 5 124010 6 123 bakery 5 7.8664 (+06) 55.42 640292 2 88402 5 5.86236 (+06) 6 163 bakery 6 1.1845 (+07) 64.74 730300 2 86250 5 6.71888 (+06) 6 163 bakery 7 2.90475 (+07) 226.24 1514804 2 280429 5 1.36659 (+07) 6 163 bakery 8 2.53131 (+08) 649.58 2823152 2 772348 5 2.57929 (+07) 6 203 blocks 2 7059 0.12 5868 2 1131 5 33658 6 175 blocks 3 695420 7.08 125260 2 22130 5 1.2631 (+06) 6 227 blocks 4 1.04907 (+08) 300.98 1999752 2 194087 5 2.20421 (+07) 6 275 elevator2 1 1728 0.02 2860 2 76 5 1743 6 55 elevator2 2 179200 0.02 3052 2 473 5 2139 6 103 elevator2 3 7.66771 (+06) 0.32 6916 2 343 5 27400 6 82 scher 1 636 0.02 2828 2 149 5 1724 6 98 34