# Introduction

Ce didacticiel est destiné aux utilisateurs maîtrisant la programmation en C ou C++, ainsi que l'architecture de la Simple Virtual Machine.

Dans ce didacticiel, vous allez commencer à écrire une extension de la machine virtuelle.

Le temps de lecture de ce didacticiel est estimé à 20 minutes.

# Mise en place

Pour commencer, créez le canevas de l'extension dans le fichier ecriture.svm_plugin en utilisant ce code :

    PLUGIN ecriture

    DEFINE

    INSTRUCTION ecriture.test
    %{
    %}

# Syntaxe générale du fichier d'extension

Le canevas de fichier d'extension présente une syntaxe particulière. Nous allons ici survoler cette syntaxe.

## Sections

Le fichier est organisé en trois sections.

### PLUGIN

Cette première section définit en premier lieu le nom de l'extension, directement placé après le mot-clef `PLUGIN`.

Ensuite, des directives peuvent être ajoutées pour décrire l'extension dans sa globalité.

### USE

Cette section contient des objets de la machine virtuelle utilisés comme dépendances. Cela signifie que le démarrage de la machine échouera si au moins un des objets de cette section n'est pas présent dans l'instance de la machine (en particulier, s'il manque une autre extension dans le fichier d'application).

Il est recommandé d'indiquer comme dépendances des objets tels qu'ils sont utilisés ou attendus par l'extension.

Modifiez le fichier pour ajouter deux dépendances :

    PLUGIN ecriture

    USE

    TYPE com.device

    WAITING INSTRUCTION com.write com.device INT INT

    DEFINE

    INSTRUCTION ecriture.test
    %{
    %}

Cela indique que lorsque cette extension est incluse, il faut également inclure une extension nommée com fournissant un type com.device et une instruction com.write qui accepte au minimum un com.device et deux entiers.

### DEFINE

Cette dernière section contient les objets fournis par l'extension. La description de ces objets sera faite en détail dans des didacticiels ultérieurs.

## Directives

Une directive est un des éléments de base de la syntaxe du fichier.

### Prologue

Une directive commence toujours par un prologue formé d'un identifiant indiquant quelle directive commence, d'une ou plusieurs options également représentées sous forme d'identifiants et se termine par un caractère deux-points (:).

### Valeurs

Après le prologue, les directives peuvent demander des valeurs.

Certaines valeurs doivent être spécifiées par une chaine de caractères, commançant et terminant par une double-quote (") et sans retour à la ligne.

D'autres valeurs doivent être spécifiées par un bloc de texte :

- un bloc vide peut être indiqué par `%{}`,
- un bloc non vide peut être indiqué en plaçant le marqueur de début `%{` en fin de ligne, puis en écrivant le texte du bloc, puis le marqueur de fin `%}` en début de ligne,
- les marqueurs de début et de fin peuvent être remplacés par `${` et `$}`, ou par `:{` et `:}` si cela s'avère nécessaire.

- Un fichier d'extension est composé de trois sections : `PLUGIN`, `USE` et `DEFINE`.
- Les sections peuvent contenir des objets de la machine virtuelle ou des directives ayant un prologue et des valeurs.

# Directives de code

Avant de pouvoir définir les premiers objets de l'extension, quelques directives présentes dans la section `PLUGIN` peuvent être utiles.

## Langage

Modifiez le fichier pour ajouter le langage utilisé par l'extension :

    PLUGIN ecriture
    lang: "C++"

    USE

    TYPE com.device

    WAITING INSTRUCTION com.write com.device INT INT

    DEFINE

    INSTRUCTION ecriture.test
    %{
    %}

Cette directive s'appelle `lang`, n'a pas d'option et accepte une valeur chaine qui précise :

- le langage utilisé. Le C++ est utilisé si la chaine contient "++", et le C est utilisé sinon,
- le standard du langage utilisé (ici, comme cela n'est pas précisé, le C++14 est utilisé).

## Inclusions

Le code de l'extension peut nécessiter l'inclusion de fichiers d'en-tête C ou C++.

Modifiez le fichier pour ajouter des en-têtes :

    PLUGIN ecriture
    lang: "C++"

    includes:
    %{
    #include <iostream>
    #include <map>
    %}

    USE

    TYPE com.device

    WAITING INSTRUCTION com.write com.device INT INT

    DEFINE

    INSTRUCTION ecriture.test
    %{
    %}

Cette directive s'appelle `includes` et accepte uniquement un bloc contenant le code en C/C++ d'inclusion des en-têtes.

## Code

Lorsque l'extension a besoin de définir des structures ou des fonctions en C/C++ qui pourront être utilisés dans le code des objets de la machine virtuelle.

Modifiez le code pour ajouter la définition d'une structure en C++ :

    PLUGIN ecriture
    lang: "C++"

    includes:
    %{
    #include <iostream>
    #include <map>
    %}

    code:
    %{
    struct O
    {
    	O()
    	:_i(0) {}
    	long int _i;
    };

    static O _o;
    %}

    USE

    TYPE com.device

    WAITING INSTRUCTION com.write com.device INT INT

    DEFINE

    INSTRUCTION ecriture.test
    %{
    %}

Cette directive s'appelle `code` et accepte également uniquement un bloc de texte. Le code en C++ présent dans le bloc peut contenir des structures, des classes, des fonctions et des définitions template.

## Options de compilation et de liage

Modifiez le code de l'extension :

    PLUGIN ecriture
    lang: "C++"

    compile: "-g -O3"
    link: "-lm"

    includes:
    %{
    #include <iostream>
    #include <map>
    %}

    code:
    %{
    struct O
    {
    	O()
    	:_i(0) {}
    	long int _i;
    };

    static O _o;
    %}

    USE

    TYPE com.device

    WAITING INSTRUCTION com.write com.device INT INT

    DEFINE

    INSTRUCTION ecriture.test
    %{
    %}

La directive `compile` permet d'ajouter des options sur la ligne du compilateur C/C++. Ces options sont également placées sur la ligne d'appel au lieur C/C++.

La directive `link` ajoute en plus des options uniquement sur la ligne du lieur C/C++.

# Directives d'extension

## Initialisation et finalisation

Une extension peut avoir besoin d'initialiser des valeurs lors du démarrage de la machine, et de les libérer lors de l'arrêt de la machine.

Modifiez le code :

    PLUGIN ecriture
    lang: "C++"

    compile: "-g -O3"
    link: "-lm"

    includes:
    %{
    #include <iostream>
    #include <map>
    %}

    code:
    %{
    struct O
    {
    	O()
    	:_i(0) {}
    	long int _i;
    };

    static O _o;
    %}

    initialisation:
    %{
    	_o._i = 1;
    	std::cout << "Start" << std::endl;
    %}

    finalisation:
    %{
    	_o._i = 0;
    	std::cout << "End" << std::endl;
    %}

    USE

    TYPE com.device

    WAITING INSTRUCTION com.write com.device INT INT

    DEFINE

    INSTRUCTION ecriture.test
    %{
    %}

La directive `initialisation` permet de préciser quel code appeller lorsque la machine démarre, et la directive `finalisation` permet de préciser quel code appeller lorsque la machine s'arrête.

Ici, la valeur statique est modifiée, et un message est émis sur la sortie standard.

Vous pouvez générer l'extension, la compiler, regarder le code C++ généré, et l'utiliser dans une application de test pour vérifier que la machine virtuelle respecte bien les différentes directives de l'extension.

## Démarrage

Il existe une autre fonction d'extension pouvant parfois être très pratique : `startup`. Cette directive permet de préciser quel code sera joué entre le démarrage des ordonnanceurs et celui des processus de l'application. En particulier, il est possible dans cette fonction de créer des processus (de préférence en terminaison automatique) et de les attacher à un ordonnanceur directement depuis le code d'une extension.

Sa déclaration et son utilisation étant assez proche de la directive `initialisation`, l'ajout d'une directive de démarrage est laissée en exercice au lecteur.

- La directive `lang` permet de spécifier le langage de génération de l'extension.
- La directive `includes` permet d'inclure des en-têtes C ou C++ dans le fichier généré.
- La directive `code` permet d'ajouter des définitions en C ou C++ dans le fichier généré. Notez qu'il est également possible d'insérer une directive de code entre des définitions d'objets dans la section `DEFINE` de l'extension.
- La directive `compile` permet d'ajouter des options de compilation et liage C/C++.
- La directive `link` permet d'ajouter des options de liage C/C++.
- La directive `initialisation` permet de lancer du code lorsque la machine démarre.
- La directive `startup` permet de lancer du code juste avant le démarrage de l'application.
- La directive `finalisation` permet de lancer du code lorsque la machine s'arrête.

# Conclusion

Vous venez de voir comment débuter l'écriture d'une extension pour la machine virtuelle.

La syntaxe du fichier a été conçue pour être très simple et répétitive pour une prise en main rapide de l'écriture des extensions.

Même si pour le moment il n'a pas été expliqué comment définir des objets pour la machine virtuelle, les directives présentées dans ce didacticiel seront parfois indispensables pour pouvoir définir correctement l'extension et les objets qui la composent.