Add soutenance
This commit is contained in:
parent
503710ad88
commit
3cc925196b
152
soutenance.md
Normal file
152
soutenance.md
Normal file
@ -0,0 +1,152 @@
|
||||
# Rapport C-repl en C++
|
||||
|
||||
## Architecture
|
||||
|
||||
### Lexer (Alaric, lexer.cpp)
|
||||
|
||||
Première étape de l'interprétation du langage. Le code à l'état brut est transformé en un tableau de tokens.
|
||||
Le lexer avance dans le texte en essayant de matcher chaque type de token, parfois à l'aide de `regex`, dans un ordre bien choisi.
|
||||
Lors de cette étape, les constantes littérales sont d'ores et déjà parsées et stockées dans leur type interne.
|
||||
|
||||
|
||||
### Parsing (Augustin, parser.cpp)
|
||||
|
||||
Le parser transforme le tableau de tokens en un `AST (Abstract Syntax Tree)`.
|
||||
Il procède par backtracking en suivant les règles de la grammaire définie dans `types.hpp`.
|
||||
|
||||
|
||||
### Analyse statique (Augustin, analysis.cpp)
|
||||
|
||||
Avant d'exécuter le programme, cette étape infère le type de chacun des éléments du programme (stocké sous forme d'`AST`) et vérifie la validité de chaque opération.
|
||||
|
||||
Une "mémoire virtuelle", copie affaiblie de la mémoire actuelle de la repl, sert à stocker les types des variables.
|
||||
Le type de chaque noeud de l'`AST` est calculé récursivement puis la validité des types passés aux opérateurs est vérifiée,
|
||||
en s'appuyant notamment sur les règles de casting définies dans `casting.cpp`.
|
||||
|
||||
|
||||
### Évaluation (Alaric, eval.cpp)
|
||||
|
||||
Les noeuds de l'`AST` sont évalués de manière récursive.
|
||||
Des exceptions sont utilisées en interne pour traiter les instructions `break`, `continue` et `return`.
|
||||
|
||||
|
||||
### Mémoire (Alaric, memory.cpp)
|
||||
|
||||
`Memory` définit une structure de mémoire réutilisable qui sert lors de l'analyse statique et de l'évaluation.
|
||||
Elle gère notamment les `scopes`.
|
||||
|
||||
|
||||
#### Types (types.hpp)
|
||||
|
||||
Rassemble les définitions de type communes à tout le projet.
|
||||
|
||||
|
||||
#### Execute (execute.cpp)
|
||||
|
||||
Encapsule toutes les étapes de l'interprétation du code brut aux résultats.
|
||||
|
||||
|
||||
#### Lecture de l'entrée (main.c, input.c)
|
||||
|
||||
Gère le traitement des arguments en ligne de commande et l'interface utilisateur de la repl: la partie "interactive" de la repl.
|
||||
|
||||
|
||||
#### Casting (casting.cpp)
|
||||
|
||||
Définit les règles de casting entre les types.
|
||||
|
||||
|
||||
#### Erreurs (errors.cpp)
|
||||
|
||||
Définit les erreurs, leur affichage.
|
||||
|
||||
|
||||
#### Utilitaires (utils.cpp, debug.cpp)
|
||||
|
||||
Fonctions utilitaires et de débogage.
|
||||
|
||||
|
||||
## Appropriation
|
||||
|
||||
Certaines parties du langage C ne sont pas spécifiées dans le standard et varient ainsi d'un compilateur à l'autre. Nous avons parfois fait des choix arbitraires, en privilégiant l'option la plus naturelle.
|
||||
|
||||
La repl ne permet pas les `undefined behavior` dans la mesure où ceux-ci sont protégés par le C++.
|
||||
Par exemple, il n'est pas possible de lire une variable non-initialisée: cela produira une erreur.
|
||||
|
||||
Il a été choisi que toute instruction ait une valeur et un type. Cela permet d'afficher une valeur de retour à l'utilisateur lorsqu'il entre une ou plusieurs instructions.
|
||||
Pour les `statements`, ce type est toujours `void`, représenté en interne par la valeur `monostate`. Cependant, certaines `expression-statements` peuvent avoir un type non-`void`. Les `expressions` ont évidemment une valeur.
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
### Types
|
||||
|
||||
Les types `int`, `double`, `void` et les fonctions composées de ces mêmes types sont supportés.
|
||||
|
||||
|
||||
### Instructions
|
||||
|
||||
Les instructions suivantes sont implémentées:
|
||||
|
||||
- Opérateurs arithmétiques binaires (`+`, `-`, `*`, `/`, `%`) et unaires (`+`, `-`)
|
||||
- Opérateurs logiques (`&&`, `||`, `!`)
|
||||
- Opérateurs de comparaison génériques (`==`, `!=`)
|
||||
- Opérateurs de comparaison arithmétique (`<=`, `<`, `>=`, `>`)
|
||||
- Opérateurs d'incrémentation gauche et droite (`++`, `--`)
|
||||
- Opérateur virgule (`,`)
|
||||
- Déclarations de variables avec et sans initialisation (`int x;`, `int x = 1;`)
|
||||
- Assignation de variables (`x = 1`)
|
||||
- Conditionnelles (`if (..) ..`, `if (..) .. else (..) ..`)
|
||||
- Boucles (`for`, `while`) avec contrôle (`break`, `continue`)
|
||||
- Définition de blocs (`{}`)
|
||||
- Déclaration de fonctions avec et sans corps (`int foo(int x);`, `int foo(int x) { .. };`)
|
||||
- Appels de fonctions (`foo(1)`)
|
||||
|
||||
|
||||
### Scopes et closures
|
||||
|
||||
L'interpréteur prend en charge les `scopes` de bloc et de fonction, ainsi que pour les `for`, comme attendu dans le langage C.
|
||||
Il gère également les `closures` comme il se doit dans un langage impératif non-fonctionnel.
|
||||
Une implémentation qui convient à ce type langage (mais pas aux langages multi-paradigmes) est une tableau de pointeurs.
|
||||
|
||||
|
||||
### Contrôle de flot
|
||||
|
||||
La repl ne comporte pas de contrôle de flot avant l'évaluation-même de l'AST.
|
||||
En conséquence, les erreurs associées sont détectées à la volée lors de l'évaluation.
|
||||
|
||||
|
||||
### Erreurs
|
||||
|
||||
La repl comporte un système d'erreur riche avec messages d'erreur et position dans le code.
|
||||
Celles-ci sont divisées en 4 catégories en fonction de l'étape à laquelle elles interviennent:
|
||||
|
||||
- `SyntaxError`: lexer et parsing
|
||||
- `ControlError`: en raison de l'absence de contrôle de flot préalable, à divers endroits
|
||||
- `TypeError`: analyse statique
|
||||
- `RuntimeError`: évaluation
|
||||
|
||||
Les `RuntimeErrors` sont accompagnées d'une `stack trace` contenant la position dans le code des appels de fonction récursifs.
|
||||
|
||||
|
||||
### Librairie standard
|
||||
|
||||
Les fonctions suivantes sont proposées pour interagir directement avec la repl:
|
||||
|
||||
- `clear_memory()` réinitialise la mémoire (non supporté hors de la scope globale)
|
||||
- `dump_memory()` affiche l'état actuel de la mémoire
|
||||
- `dump_history()` affiche l'historique du code passé en entrée
|
||||
|
||||
|
||||
### Interface utilisateur
|
||||
|
||||
Le système d'entrée est pratique : il permet de se déplacer dans la ligne actuelle et de naviguer dans l'historique du code entré.
|
||||
Les lignes sont automatiquement numérotées pendant que la saisie.
|
||||
Pour permettre les sauts de ligne multiples, il est nécessaire de taper `;;` pour indiquer au programme que l'on a terminé son entrée.
|
||||
Le résultat de l'évaluation du programme est alors affiché.
|
||||
|
||||
|
||||
## Tests
|
||||
|
||||
Une suite de tests automatisée est disponible : elle teste les différentes parties du code, les fonctionnalités du langage ainsi que chaque type d'erreur.
|
||||
Des programmes plus conséquents sont disponibles dans `./example`.
|
BIN
soutenance.png
Normal file
BIN
soutenance.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 371 KiB |
Loading…
Reference in New Issue
Block a user