diff --git a/README.md b/README.md index 79d3668..22ef26d 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,9 @@
+ +> On fait le choix d'être noter en priorisant la partie interprétation du code, puis la partie compilation. + ## 🗂️ Structure du projet ```text @@ -63,3 +66,176 @@ Utilisez `node ./bin/cli` pour afficher les options disponibles ou `node ./bin/c ## 🖼️ Screenshots ![Demo](mini-mecha-code/doc/timeline.gif) + +## Choix technique + +Tout d'abord, il faut savoir que notre grammaire définie avec notre projet Xtext est relativement éloignée de celle qu'on retrouve sur notre projet Langium. +On avait commencé par faire une grammaire avec Xtext, mais on a eu des problèmes pour la convertir en Langium, on a donc décidé de repartir presque de zéro. + +Néanmoins, les principaux choix ont été pris lorsque de la conception de la grammaire Xtext. + +### 📜 Grammaire + +On a décidé de faire une grammaire relativement simple, qui couvre la plupart des besoins du projet que l'on a définis en utilisant les exemples fournis dans le sujet. + +Voici un diagramme de la grammaire : + +```mermaid + +classDiagram + class Model { + +DefFunction[] functions + } + class Statement + class VarAssignment + class Expression + class PrimaryExpression + class UnitOperator + class DefVariable { + +Type varType + +String name + +Expression value + } + class FunctionParameter + class NumberLitteral + class RefVariable + class BooleanLitteral + class DefFunction { + +Type returnType + +String name + +FunctionParameter[] parameters + +Statement[] statements + +Expression returnValue + } + class Loop + class Minus + class Multi + class Div + class Plus + class Greater + class Less + class Equal + class Or + class And + class Not + class FunctionCall { + +DefFunction ref + +Expression[] parameters + } + class Rotate + class Forward + class Convertion + + Model --> DefFunction + Statement <|-- DefVariable + Statement <|-- Loop + Statement <|-- FunctionCall + Statement <|-- Rotate + Statement <|-- Forward + Statement <|-- VarAssignment + Expression <|-- PrimaryExpression + Expression <|-- Plus + Expression <|-- Minus + Expression <|-- Multi + Expression <|-- Div + Expression <|-- Greater + Expression <|-- Less + Expression <|-- Equal + Expression <|-- Or + Expression <|-- And + Expression <|-- UnitOperator + Expression <|-- Convertion + Expression <|-- Not + PrimaryExpression <|-- NumberLitteral + PrimaryExpression <|-- RefVariable + PrimaryExpression <|-- BooleanLitteral + PrimaryExpression <|-- FunctionCall + VarAssignment --> DefVariable + VarAssignment --> Expression + UnitOperator --> PrimaryExpression + DefFunction --> Type + DefFunction --> FunctionParameter + DefFunction --> Statement + DefFunction --> Expression + Loop --> Expression + Loop --> Statement + FunctionCall --> DefFunction + FunctionCall --> Expression + Rotate --> Expression + Forward --> Expression + Convertion --> PrimaryExpression + +``` + +- Le programme est composé de plusieurs fonctions. + - Il n'est pas possible de définir des variables globales. + - Il n'est pas possible de définir des fonctions dans des fonctions. +- On peut utiliser des opérateurs arithmétiques (`+`, `-`, `*`, `/`), de comparaison (`>`, `<`, `==`) et des opérateurs logiques (`&&`, `||`, `!`). + - On a décidé qu'en arrière-plan , toutes les valeurs seront des nombres flottants, et que les booléens seront représentés par `0` et `1`. Cela permet de simplifier l'implémentation. +- Il est possible d'utiliser des mots clés prédéfinis (`Clock`, `Forward`). Comme ces mots clés sont utilisés d'une manière différente qu'un appel classique de fonction, on a décidé de les traiter comme des opérateurs. +- On profite de Langium et de sa gestion des références pour faire en sorte que les fonctions et les variables soient définies avant d'être utilisées, et que les interfaces en arrière-plan contiennent une référence vers la définition de la fonction ou de la variable. +- On a décidé de ne pas utiliser de `;` pour séparer les instructions, mais plutôt de les séparer par des retours à la ligne. Cela permet de simplifier la grammaire et de ne pas avoir à gérer les cas où il y a plusieurs `;` à la suite. +- Les appels de fonctions sont classiques, on utilise `nomFonction(param1, param2, ...)`. + - On a fait le choix de ne pas inclure les fonctions tel que `getSpeed()` ou `getTimestamp()` dans la grammaire, car on a décidé de les traiter comme des fonctions prédéfinies (présentes dans la STD). + +### 📦 Architecture + +#### 🗣️ Communication client-serveur + +On a décidé d'utiliser le canal ouvert par défaut lorsque l'on utilise le langage server sur le client. Cela permet de communiquer via l'envoi de messages (via l'utilisation d'une connexion WebSocket). + +```mermaid +sequenceDiagram + actor U as Utilisateur + participant C as Client + participant S as Serveur + + U ->> C: Tape du code + C ->> S: Demande de validation + S ->> C: Résultat de la validation + rect blue + S ->> C: Résultat de l'interprétation + + U ->> C: Clique sur "Run" + C ->> C: Execution du résultat de l'interprétation + end +``` + +On intercepte la communication entre le client et le serveur pour pouvoir afficher les erreurs de validation, et on interprète directement le code à la volée. + +Le résultat de l'interprétation est ensuite traité par le client et affiché lorsque l'utilisateur clique sur le bouton "Run". + + +#### 📦 STD + +Afin de profiter de la puissance de Langium, on a décidé de faire une STD (Standard Type Definition) qui contient les fonctions prédéfinies du langage. +Cela nous permet notamment de pouvoir utiliser les mêmes règles de validations que pour les fonctions définies par l'utilisateur. + +Cette STD est injectée via le fichier `mini-mecha-code/src/language/mini-mecha-code-workspace-manager.ts`, en suivant la [documentation de Langium](https://langium.org/guides/builtin-library/). + +Néanmoins, nous avons fait face à un problème lors d'utilisation de cette STD avec la CLI (aucune documentation éxiste). Nous avons donc fait le choix de désactiver la validation lorsque l'on utilise la CLI. Le code Adruino est néanmoins généré correctement. + +#### 📦 Validation (`mini-mecha-code/src/language/mini-mecha-code-validator.ts`) + +Voici les règles de validation que l'on a défini : + +- Vérifier si une variable définie (`defVariable`) n'est pas déjà définie dans le même bloc de code ou en tant que paramètre de la fonction englobante. +- Vérifier si une fonction (`DefFunction`) n'est pas déjà définie dans le modèle global ou parmi les fonctions intégrées. +- Vérifier que le programme a une fonction d'entrée (`entry`). +- Vérifier que la fonction d'entrée n'utilise pas de paramètres. +- Vérifier si un appel de fonction (`FunctionCall`) utilise le bon nombre de paramètres par rapport à la définition de la fonction appelée. + +#### 👷 Interprétation (`mini-mecha-code/src/interpretor/interpretor.ts`) + +On a fait le choix de ne pas utiliser de pattern visitor pour l'interprétation, mais plutôt d'utiliser des fonctions récursives, ainsi que les fonctions `is