Ce fichier est lu (et son contenu exploité) par un appel à la fonction ParseStructureFile. Cette fonction prend en argument le nom physique du fichier. Cet appel peut figurer dans le programme principal ... :int main(int argc, char* argv[]) { ... ParseParameterFile(argv[1]); ParseSimulationFile(argv[2]); ... ParseStructureFile(argv[4]); ... pCurrentSim->Run(); ... }... auquel cas le nom du fichier peut être passé en argument de la ligne de commande. Par exemple :
./main sim1.par sim1.sim sim1.osp sim1.par ...L'appel peut aussi résulter d'une directive de simulation écrite sur un fichier externe (voir plus haut la page sur le fichier des directives), auquel cas le nom du fichier sera un des éléments de la directive.
Quoi qu'il en soit, l'appel à ParseStructureFile doit figurer après l'appel à ParseParameterFile si la mise en place d'un élément de la structure requiert que des paramètres du système soient déjà connus en mémoire (donc accessibles par Get..ParameterValue).
De même, il doit figurer avant l'appel à Run, laquelle requiert naturellement l'instanciation préalable du système.
Le fichier de description de la structure n'est pas présenté ici de façon formelle, sur le modèle utilisé pour les autres fichiers, mais en considérant successivement les différents sens qu'on souhaite donner aux expressions.
- La trace des opérations de lecture/interprétation est initiée par :
TRACE PARSING;La trace est arrêtée par :TRACE NO_PARSING;- L'inclusion d'un fichier est commandée par :
INCLUDE <chemin>;où <chemin>} est le nom complet (absolu ou relatif) du fichier inclus.
La dernière ligne du fichier inclus doit être :END INCLUDE;- On crée une variable locale temporaire entière (ou réelle, ou à valeur chaîne de caractères), et on lui affecte une valeur résultat de l'évaluation de l'expression entière <int_expr> (ou réelle <real_expr>, où à valeur chaîne de caractères <str_expr>), par :
{i1} = <int_expr>; {x9} = <real_expr>; {s1} = <str_expr>;Les indices valides pour i., x. et s. sont les entiers de 1 à 10.
Les expressions <int_expr> et <real_expr> sont construites avec les règles énoncées pour <int_expr> dans la page consacrée au fichier de spécification de la simulation. Les expressions <str_expr> sont une chaîne de caractères, la référence à un paramètre à valeur chaîne de caractères (avec le préfixe <ps>) ou bien plusieurs <str_expr> séparées par l'opérateur ^ signifiant la concaténation.- On demande la création d'une nouvelle instance d'entité de la classe de nom nom_c par :
+ I nom_c nom_i; // ou + I nom_c nom_i,; ou encore + I nom_c,;nom_c et nom_i sont des chaînes de caractères simples (e.g abc) ou multiple, encadrées alors par des guillemets (e.g "abc dfe"). Les caractères autorisés sont les lettres et le caractère '_' et, sauf pour le premier caractère, les chiffres, '.' et ':'.
Cette requête invoque un constructeur de l'entité codé dans le fichier UserFunction.cc. Ce constructeur est déterminé dans la fonction App_NewEntityFromString (voir page 'Fonctions globales/Création d'instances de classes') en fonction de la chaîne de caractères passée en argument (ici nom_c).
Comme le constructeur invoqué n'attribue généralement pas de nom d'instance, un nom d'instance par défaut sera attribué par DIESE (voir page 'La classe des entités sans descripteurs ni méthodes/Identification de l'entité').
Ce nom par défaut est remplacé par un nom choisi, e.g. nom_i, si on écrit :+ I nom_c nom_i;- On demande l'ajout à nom_i d'un nouveau composant de la classe de nom nom_cc., et d'éventuel nom d'instance nom_ic. par l'une des notations de l'exemple suivant :
+ I nom_c nom_i, + C nom_cc1, ; // noter la virgule + C nom_cc2 nom_ic2 ; + C nom_cc3 nom_ic33, ; ;Noter que de façon générale il n'y a aucune contrainte de retour à la ligne ou d'indentation. Dans le dernier exemple, le ; final (qui clôt la déclaration de {\t nom_i}) peut suivre le précédent sur la même ligne. \- De même, on demande l'ajout à nom_i d'un nouvel élément de la classe de nom nom_ce par :
+ I nom_c nom_i, + E nom_ce1, ; + E nom_ce2 nom_ie2 ; + E nom_ce3 nom_ie3, ;;- On fait référence à une entité déjà créée, de classe nom_c et nommée nom_i, en écrivant une des lignes suivantes :
<I><nom_c nom_i> <I><nom_c nom_i,> <I><nom_c,> <I><,nom_i>Si on ne désigne l'entité que par un nom de classe, c'est la première entité de la classe à avoir été instanciée qui sera désignée.On pourra désigner cette entité comme étant l'"entité simulée" (cf. page 'La classe des simulations'), par :
ENTITE_SIMULEE <I><nom_c nom_i>;- On demande pour nom_i l'ajout d'un composant déjà créé de nom de classe nom_cc par :
+ I nom_c nom_i, <- C <I><nom_cc,>;;- On demande pour ce composant l'ajout d'éléments déjà créés de nom d'instance nom_ie1 et nom_ie2 par :
+ I nom_c nom_i, <- C <I><nom_cc,> <- E <I><,nom_ie1>; <- E <I><,nom_ie2>; ; ;- On établit la valeur de descripteurs de noms de classe d1, de l'entité nom_i par les expressions suivantes, selon que la valeur est, dans l'ordre, un nombre entier (d11), un nombre réel (d12), une fonction entière ou réelle de la valeur d'une variable locale temporaire (d13), une chaîne de caractères (d14), une date (d15, noter les guillemets), la valeur d'un paramètre du système, d'abord entier (d21), puis réel (d22) et à valeur chaîne de caractères (d23):
+ I nom_c nom_i, d11 = 1; d12 = 0.5; d12 = EPS; d12 = <int_expr>/<int_expr>; d13 = {i1}*3+{x2}; d14 = str1^str2; d15 = "21/08/2008"; d21 = <pi><str1 str2>; d22 = <pr><str1 str3>/2; d23 = <ps><str1 str2>; d7 = + I ,nom_i1; ; d8 << <I><,nom_i2>; d8 << 5 15 18; d9 << (0 <int_expr>); ;Les descripteurs (d7), (d8), (d9) et (d10) sont respectivement de type 'entité', 'tableau d'entité', tableau d'entiers et 'tableau d'intervalles d'entiers'. Les éléments de valeur à droite du symbole d'affectation << sont ajoutées à la fin de la liste des élements de valeur déjà présents.
Ces manières d'affecter une valeur à un descripteur s'appliquent dans tous les contextes de déclaration d'entité (nouvelle, déjà créée, composant ou élément à quelque niveau que ce soit)
On voit en outre que les spécifications de construction de la structure et les affectations de valeurs peuvent être entremêlées. La valeur du descripteur (d7) est construite au moment de l'affectation (remarquer des deux ";" successifs).- On peut affecter des fonctions prédéfinies comme corps aux méthodes (instances de Method) des entités. Dans la présente version de DIESE, seulement deux fonctions sont prédéfinies, toutes deux de type bool, l'une retournant toujours vrai, l'autre retournant toujours faux. On réalise cela par les lignes suivantes, où a_predicate et b_predicate sont les noms de classe des instances de Method attachées à l'entité nom_i :
+ I nom_c nom_i, (BOOLEAN) a_predicate -> ALWAYS_TRUE; (BOOLEAN) b_predicate -> ALWAYS_FALSE; ;- La structure d'une entité est affichée par une requête commençant par le groupe de mots AFFICHER STRUCTURE suivi d'une référence à une entité déjà créée (voir plus haut) et terminée par ;.
- Les valeurs des descripteurs d'une entité sont affichées par une requête commençant par le groupe de mots AFFICHER DESCRIPTEURS suivi d'une référence à une entité déjà créée (voir plus haut) et terminée par ;.
- On demande la création d'une nouvelle instance de spécification d'ensemble d'entités de nom de classe nom_c par :
+ SpE nom_c;- Des spécifications complémentaires peuvent être exprimées sur la spécification d'ensemble d'entités de la manière suivante, à titre d'exemples indépendants:
REFCLASS_ID = VOITURE; REFCLASS_NAME = voiture; EFFECTIF = 2; QUANTIFICATEUR = 1; // pour NFIRST, ou 2 pour ALLENT MODE = 1; // pour RETURN_INSTANCES et 2 pour INSTANTIATE REF_ENTITY = <I><, maVoiture>;
- On demande la création d'une nouvelle instance de processus (continu ou ponctuel) de nom de classe nom_c et de nom d'instance nom_i (noter que les deux informations sont requises et que, comme pour les entités, elles ont la forme d'une chaîne simple ou multiple) par :
+ P nom_c nom_i;Cette requête invoque un constructeur du processus codé dans le fichier UserFunction.cc. Ce constructeur est déterminé dans la fonction App_NewProcessFromString (voir page 'Fonctions globales/Création d'instances de classes') en fonction de la chaîne de caractères passée en argument (ici nom_c).
Si ce constructeur n'affecte pas explicitement de valeur au pas ou au délai de ré-examen, la valeur 1 leur est attribuée par défaut.- On fait référence à un processus déjà créé, de classe nom_c et nommé nom_i, en écrivant :
<P><nom_c nom_i>ou, en n'utilisant que le nom d'instance (noter la position de la virgule) :<P><,nom_i>- Des spécifications complémentaires peuvent être exprimées sur un processus. Dans la déclaration suivante, portant sur le processus nommé nom_i, et successivement, on affecte une valeur au pas, au délai de ré-examen, on désigne l'entité qui est l'objet du processus (nom_io) :
<P><,nom_i> PAS = 2; DELAI = 5; ENTITE_CIBLE = <I><,nom_io>; ;Si le processus est un processus continu, on peut, au même niveau que les déclarations ci-dessus, programmer un événement d'initialisation :<P><,nom_i> INIT_EVT DATE_OCCUR = 0; //DATE_OCCUR = 21/08/2008; //DATE_OCCUR = 21/AOU/2008 12/0/0; //DATE_OCCUR = 21/AOU/2008 <pi><"occur" "heure">/0/0; PRIORITE = 1; ;ou bien un événement d'initialisation et de poursuite, ou encore de poursuite simplement, en remplaçant le mot-clé INIT_EVT par INIT_PRCD_EVT ou PRCD_EVT. Bien noter que cette programmation doit être la dernière spécification complémentaire du processus.
Si le processus est un processus de lecture de fichier séquentiel, on peut, au même niveau que les déclarations ci-dessus, déclarer le symbole de classe du fichier à lire, et l'une ou les autres des informations sur le nom du fichier à lire :
FILE_ID = FICHIER_METEO; REPERTOIRE_FICHIER "/home/durand/mesBases/in/"; //NOM_SIMPLE_FICHIER "meteo1.txt"; NOM_COMPLET_FICHIER "/home/durand/mesBases/in/meteo1.txt";On peut aussi écrire :
REPERTOIRE_FICHIER {s1};... si {s1} est une variable locale (de type 'chaîne de caractères', vu sa lettre-préfixe) à laquelle on a préalablement affecté la valeur appropriée :
{s1} = "/home/durand/mesBases/in/";ou
{s1} = IN_DIR "in/";... si on a utilisé la directive IN_DIR dans le fichier des spécifications de la simulation.
- On demande la création d'une nouvelle instance d'événement de nom de classe nom_c et de nom d'instance nom_i (noter que les deux informations sont requises et que, comme pour les entités, elles ont la forme d'une chaîne simple ou multiple) par :
+ V nom_c nom_i;Cette requête invoque un constructeur d'événement codé dans le fichier UserFunction.cc. Ce constructeur est déterminé dans la fonction App_NewEventFromString (voir page 'Fonctions globales/Création d'instances de classes') en fonction de la chaîne de caractères passée en argument (ici nom_c). L'événement est inséré dans l'agenda d'événement de l'instance de Simulation pCurrentSim (voir page 'Variables globales'). \ Si ce constructeur n'affecte pas explicitement de valeur à la date d'occurence ou à la priorité, les valeurs 0 et 99 leur sont attribuées respectivement par défaut.- On fait référence à un événement déjà créé, de classe nom_c et nommé nom_i, en écrivant :
<V><nom_c nom_i>ou, en n'utilisant que le nom d'instance :<V><,nom_i>- Des spécifications complémentaires peuvent être exprimées sur un événement. Dans la déclaration suivante, portant sur l'évenement nommé nom_i, et successivement, on affecte une valeur à la date d'occurence (par tirage au sort uniforme entre deux bornes, ou directement (ici : 20), ou par une date calendaire), à la priorité, à la probabilité d'occurrence et, pour le cas où l'événement est autogénérable, une valeur aux délais minimum et maximum d'occurrence de l'événement autogénéré :
<V><,nom_i> //MIN_DATE_OCCUR = 0; //MAX_DATE_OCCUR = 30; DATE_OCCUR = 20; //DATE_OCCUR = 21/JAN/2008); // ou 21/JAN/2008 0/0/0) //DATE_OCCUR = 21/JAN/-9); // millésime = celui à l'instantiation PRIORITE = 1; PROBABILITE = 0.667; MIN_DELAY_NEXT = 5; MAX_DELAY_NEXT = 10; ;Au même niveau que les déclarations ci-dessus, on peut définir des directives en termes d'actions sur des processus (et on le fait normalement de la manière suivante, en faisant obligatoirement référence à un ou des processus déjà créés) :<V><,nom_i> PROCESS_ACTION = {<P><,nom_ip1> (INIT PROCEED), <P><nom_cp, nom_ip2> (EXEC)}; ;On peut aussi déclarer quelle sera l'entité touchée par un des processus gérés par l'événement (en faisant obligatoirement référence, d'une manière ou d'une autre, à une entité déjà créée). Par exemple :<V><,nom_i> ENTITE nom_cp = <I><,nom_io>; //I nom_cp = <I><,nom_io>; // forme equivalente; //ENTITE_CIBLE nom_cp = <I><,nom_io>; // forme equivalente ;Si l'événement gère un processus de lecture de fichier séquentiel, on peut, au même niveau que les déclarations ci-dessus, déclarer l'une ou les autres des informations sur le nom du fichier à lire, avec les mêmes expressions qu'au niveau du processus. Les spécifications sur l'événement surchargent celles faites sur le processus et sur le fichier lui-même.- On demande la création d'une nouvelle instance de fichier en série d'enregistrements de symbole de classe symb_c par :
+ SDF symb_c;Cette requête invoque un constructeur de SequentialDataFile codé dans le fichier UserFile.cc. Ce constructeur est déterminé dans la fonction App_NewSequentialDataFileFromString (voir page 'Fonctions globales/Création d'instances de classes') en fonction de la chaîne de caractères passée en argument (ici symb_c).
Ce paragraphe d'instantiation de fichier peut inclure les informations sur le chemin d'accès (répertoire, nom simple, nom complet) avec les mêmes expressions que dans la déclaration d'un processus de lecture. Ce qu'on écrit ici vient surcharger les instructions de même effet placées dans le constructeur.
On peut aussi ajouter la directive d'ouverture du fichier, da la manière simple suivante :
OUVERTURE;- A tout moment dans la séquence de spécifications, on peut demander l'affichage du contenu de l'agenda d'évenements, par AFFICHER AGENDA;
- Toute fin de ligne après // ou # est ignorée, de même que tout passage entre /
et la fin d'une ligne commençant par
/.
- Toute spécification de structure <spec> peut être exprimée conditionnellement. <spec> peut être simple ou complexe et inclure une spécification conditionnelle :
SI <condition> <spec> FIN SI SI <condition> <spec> SINON <altSpec> FIN SIavec :<condition> ::= <num_expr> <op_num> <num_expr> ::= <str_expr> <op_str> <num_expr> <op_num> ::= < | <= | > | >= <op_str> ::= == | !=- Certaines spécifications de structure peuvent être itérées, sous le contrôle d'une variable entière. Il s'agit de la déclaration/affectation d'une variable, des spécifications de création d'entité, de processus et d'événement. Il s'agit aussi de l'ajout d'éléments aux entités. Noter qu'on ne peut pas itérer l'ajout de composants et l'affectation de valeurs aux descripteurs, ni l'affectation de valeurs aux attributs des processus et des événements. On peut imbriquer plusieurs boucles, sous le contrôle de plusieurs variables différentes. On peut ainsi écrire :
{x1} = 4.0; POUR i1 = (1) TO (3*<int_expr>) + I classeA, POUR i2 = (1) A (4) + E classeB inst{i2} x =: {x1}; ; FIN POUR ; FIN POUR ;Attention ! L'itérateur i2 ne peut pas servir d'opérateur arithmétique dans la mise en oeuvre de la boucle. On ne peut pas écrire, par exemple :... + E classeB inst{i2} x =: {x1}*{i2}; ; ...