C'est la première documentation de CodeCommander (écrite en français).
La précédente était écrite en anglais; voici la version française.

CodeCommander est un outil facile à utiliser car c'est un éditeur évolué : tout est graphique, ce n'est pas uniquement un éditeur de texte. Pour commencer, il faut récupérer les sources d'un programme informatique et importer le texte dans l'éditeur. C'est un texte brut; il n'y a pas une syntaxe particulière, ni une coloration des mots.
Il faut comprendre que le texte brut, ici, est le code source à générer et qu'il ne prétexte d'aucune syntaxe particulière.

for(int i=0; i < 10; ++i)
{
....sum += i;
}

A l'exécution de cette seule action tel qu'elle, ce texte est écrit directement dans le fichier. Pour en connaitre un peu plus sur CodeCommander, sélectionnez les mots i et sum dans l'éditeur et cliquez droit sur la sélection : une popup apparaît avec des boutons à sélectionner. La seconde action à connaitre est un marqueur avec un nom à choisir.

for(int <myVar>=0; <myVar> < 10; ++<myVar>)
{
.....<mySum> += <myVar>;
}

En deux actions, on peut personnaliser le résultat. Au moment de générer le fichier final, le programme initie une procédure de personnalisation et demande à l'utilisateur de saisir le contenu de myVar et de mySum.


A propos des légendes
Ce n'est pas très pratique de comprendre ce qu'il faut personnaliser si je me limite au nom d'une variable. C'est pourquoi, il est fortement recommandé de créer une légende pour chaque variable. Aussi, l'éditeur propose un astérisque cliquable pour définir une nouvelle légende.

Il n'y a jamais de contrôle de validation des données saisies; mais, ce serait plus raisonnable si l'on pouvait préciser le type de champ. Ainsi, il y a 3 types généraux tels que :
  1. un texte
  2. un nombre
  3. un interrupteur On/Off, Vrai/Faux, etc
  4. une sélection parmi plusieurs valeurs (énumération)


A propos de la compilation

Lors de la compilation, les actions écrites dans CodeCommander sont analysées et exécutées. Le résultat est toujours un fichier final correspondant au :
  • calcul des expressions,
  • gestion de la portée des variables au niveau de chaque processus,
  • récupération des valeurs indiquées dans le dictionnaire de personnalisation,
  • instructions de branchement,
  • squelettes,
  • injecteurs,
  • modèles,
  • programmation orientée modèle,
  • exécution en parallèle,
  • activité contrôlée des tâches et leur mise en attente de requêtes,
  • création d'un autre fichier et son écriture,
  • texte brut.

Accessoirement, le fichier final peut servir de fichier pour tout types de traces.

Le dictionnaire de personnalisation est structuré selon deux types différents : un couple nom/valeur et un tableau d'éléments indexés avec pour chacun une liste de couple nom/valeur.

La portée des variables

Les variables sont enregistrées dans une pile (au sens algorithmique du terme). A chaque lancement d'un nouveau processus, j'insère d'abord un séparateur qui permet de séparer les nouvelles variables locales au processus à lancer et les variables induites par les processus ancêtres.


Qu'est-ce qu'un processus ?

C'est simplement une routine pouvant être appelée depuis n'importe quel processus. En créant une variable dans un processus, tous les processus et les sous-processus appelés consécutivement ont en leur mémoire cette même variable et peuvent en modifier sa valeur. Une fois que le processus ayant créé cette variable est terminé, la variable est supprimée et n'existe plus du tout.

Les processus ne peuvent pas être récursifs car le pointeur de position de la prochaine instruction est attaché au processus ce qui provoquerait un comportement incohérent. Cependant, la récursivité sera primordiale pour les futures versions du logiciel.

Réagir selon l'état (les boucles)
Une autre instruction intéressante s'appelle le test d'une expression. Selon que l'expression est vraie ou fausse, le compilateur effectue une opération de branchement : la prochaine action du programme dépend de cette expression. L'opération complémentaire est un label, un nom unique dans le processus qui indique la prochaine action du compilateur.

Réagir selon l'expression calculée à chaque passage permet de créer des boucles comme l'exemple ci-dessous :
<i = 0>
<start:>
Hello world

<i=i+1>
<if(i<10;start;end)>
<end:>

Modèles
Ce n'est pas seulement difficile d'écrire toutes ces actions, c'est aussi fastidieux.
Alors, pour une meilleure visibilité et une plus grande souplesse, j'ai prédéfini certaines actions réutilisables.

Un modèle est un groupement d'actions prédéfinies et paramétrables. Les paramètres possibles sont :
  • une expression à calculer avec des opérateurs (additions, etc),
  • une chaîne de caractères alphanumériques,
  • le nom d'une variable existante ou non dans le processus courant.

Pour utiliser un modèle, les paramètres sont simplement remplacés par leur valeur au moment de la reconstruction de chaque action du modèle. Par exemple la création d'une boucle :

<template path="/" name="loop">
<params>
<param name="counter"/>
</params>
<$counter = 0>
<start:>
Hello world
<$counter=$counter+1>
<if($counter<10;start;end)>
<end:>
</template>

Pour utiliser ce modèle, j'ai ajouté une action spécifique :

<usetemplate name="/loop">
<params>
<param name="counter">i</param>
</params>
</usetemplate>

Enfin, en compilant cet exemple, le paramètre counter dans la déclaration du modèle est remplacé par l'expression indiquée dans l'utilisation du modèle, c'est-à-dire i. Le modèle a été recopié, tel quel après le remplacement des noms de paramètres commençant par le caractère $. De plus, au lieu de counter, la variable créée est bien i et pas counter.

Pourquoi donc remplacer un nom de paramètre par un autre nom ?
Je vais expliquer maintenant qu'il y a 2 autres actions plus complexes qu'il convient de traiter dans l'action modèle. La variable i permet d'utiliser ce nom de variable dans le corps du modèle ; en revanche, je ne peux pas modifier le corps du modèle que j'ai utilisé. Pour cela, j'ai défini deux autres actions : poignée (handler) et codage (coding). L'action "codage" est un label identifié par un nom que l'on crée au moment de spécialiser le modèle. L'action "poignée", que l'on ajoute à la définition du modèle, recherche si le codage spécialisé avec le même nom existe.

Au moment de la compilation des actions, toutes celles référencées dans un "codage" sont ajoutées en lieu et place de l'action "poignée". Ainsi, lorsque j'utilise la variable i dans le corps du modèle, cette variable représente le compteur de boucle. Cette variable existe bien dans la portée et, durant toute la durée de vie du modèle.

Autre chose, il est probablement intéressant de créer un processus dans la définition du modèle, cela afin que les variables locales créés par le modèle soient locales au processus créé et pas à celui qui fait appel au modèle. Je fais remarquer que pour le moment, tous les modèles que j'ai prédéfini initient un processus. En revanche, comme chaque processus doit avoir un nom différent, chaque modèle a un paramètre appelé "name" qui servira de nom au processus. Ce paramètre est à personnaliser de manière à ce qu'à chaque utilisation d'un modèle, le processus créé par le modèle est bien unique.


Last edited Aug 1, 2014 at 12:39 PM by skercrow, version 5