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 :

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 :

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.

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.