README.md 7.21 KB
Newer Older
1
2
3
4
5
# PetitJava

Un projet de compilation, dans le cadre de notre 4ème année à l'INSA de Rennes, en 2022.

Le but est de transformer un langage proche du Java *(c'est à dire avec des fonctionnalités en moins)* en un programme
Timothé Rosaz's avatar
Timothé Rosaz committed
6
strictement équivalent d'un point de vue comportemental en C.
7
8
9
10
11
12
13
14

## Auteurs

- Timothé Rosaz,
- Alexandre Sabbadin.

## Utilisation

Timothé Rosaz's avatar
Timothé Rosaz committed
15
Une fois les sources compilées, exécutez-le avec la commande suivante :
16
```bash
Timothé Rosaz's avatar
Timothé Rosaz committed
17
java -jar petitjava.jar source.pj -o sortie.c
18
19
# Puis, une fois le fichier transpilé, vous pouvez simplement le compiler en code machine
gcc sortie.c -o executable.o
Timothé Rosaz's avatar
Timothé Rosaz committed
20
# pour voir les arguments possible, vous pouvez n'en mettre aucun ou utiliser '-help'.
21
22
```

Timothé Rosaz's avatar
Timothé Rosaz committed
23
24
Ne mettez aucun argument pour afficher tous les arguments acceptés.

Timothé Rosaz's avatar
Timothé Rosaz committed
25
Si vous utilisez - pour une raison que j'ignore - ce projet dans le vôtre, merci d'indiquer l'origine du code quelque part !
26

Timothé Rosaz's avatar
Timothé Rosaz committed
27
28
29
30
31
32
33
34
35
36
37
38
## Démonstration

Une démonstration technique, un jeu de dames utilisant une grande variété de fonctionnalités de petitJava.
Compilez simplement le fichier `demo.pj` à la racine du projet, puis compilez-le sur l'OS de votre choix.

## Limitations techniques

Hélas, ce projet n'est pas parfait. Voici une liste des problèmes connus :
- Pas possible d'utiliser les opérateurs `++` et `--` en dehors de statement isolé.
- Plusieurs conditions dans un `if` nécessite de regrouper chaque élément entre parenthèse.
- Impossible d'écrire `- <valeur>` en tant que nombre. Il faut écrire `0-1` pour `-1`.
- Il peut se passer des choses étranges avec les expressions mathématiques de type `a-(b+c)`.
Timothé Rosaz's avatar
Timothé Rosaz committed
39
- Pas de garbage collecteur. C'est un gros problème.
Timothé Rosaz's avatar
Timothé Rosaz committed
40

41
42
43
## À propos du langage

Dans les grandes lignes, voici les points manquant dans notre projet :
Timothé Rosaz's avatar
Timothé Rosaz committed
44
- Pas de classe abstraite ou de `default` dans une interface,
Timothé Rosaz's avatar
Timothé Rosaz committed
45
- Pas de classe ou structure anonyme,
46
47
- le garbage collector n'est pas implémenté,
- pas de type primitifs `float`, `long`, `short` ou `byte`.
48

Timothé Rosaz's avatar
Timothé Rosaz committed
49
50
51
52
Voici, en revanche, les éléments présents :
- Système de classes, avec héritage et implémentation d'interfaces.
- Système de constructeur par défaut et de méthode avec plusieurs signatures.
- Un système de visibilité basique. Mais comme tout est dans un seul fichier, seul le "private" a un sens.
53
- Tableaux (à N dimensions) pouvant stocker des nombres comme des objets quelconques.
Timothé Rosaz's avatar
Timothé Rosaz committed
54
55
- Manipulation et concaténation de chaînes de caractères.
- Système de gestion et capture d'erreurs. Pas de stacktrace de prévue cependant.
56
- STDIN basique, avec `hasNextLine()`,`nextLine()`,`hasNextInt()`,`nextInt()`, et sans Scanner, le tout sur `System.in`.
Timothé Rosaz's avatar
Timothé Rosaz committed
57

58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
## Fonctionnement

Pour effectuer une transpilation, PetitJava fonctionne en quatre temps :
1) Tokenization,
2) Analyse syntaxique *(ou "Parsing")*,
3) Validation des types,
4) Transpilation

Voici une explication technique plus ou moins détaillée de chacune des étapes.

### 1. La tokenization

Le fichier à transpiler est dans un premier temps converti en un flux de caractères.
Ce dernier va être parcouru caractère par caractère pour former des "tokens".
Ainsi, tous les littéraux sont stockés dans un certain token, tous les mots clefs ont un token correspondant,
les commentaires sont ignorés et toute suite de caractère non reconnue est considérée comme un "identifiant".
Timothé Rosaz's avatar
Timothé Rosaz committed
74
En pratique, cela peut correspondre à un nom de classe ou de variable par exemple.
75

Timothé Rosaz's avatar
Timothé Rosaz committed
76
77
Pour voir la liste des tokens possibles, il faut voir l'énumération [TokenType](src/fr/petitjava/core/TokenType.java).
Le processus expliqué ci-dessus est accompli par la classe "statique" du [Tokenizer](src/fr/petitjava/Tokenizer.java).
78
79
80
81


### 2. L'analyse syntaxique

Timothé Rosaz's avatar
Timothé Rosaz committed
82
Cette étape est potentiellement la plus difficile. Elle consiste à produire un arbre de [classes](src/fr/petitjava/nodes/ClassNode.java) à
83
partir du flux de Token créé précédemment.
Timothé Rosaz's avatar
Timothé Rosaz committed
84
85
Chacune d'entre elle contient des [champs](src/fr/petitjava/nodes/FieldNode.java) et des [méthodes](src/fr/petitjava/nodes/MethodNode.java).
Ce sont les méthodes qui vont contenir des [statements](src/fr/petitjava/nodes/statements/StatementNode.java). Ces derniers représentent
86
une "ligne" de code comme une assignation, une déclaration, un `if` ou une quelconque structure du code.
Timothé Rosaz's avatar
Timothé Rosaz committed
87
Dans ces statements, on retrouve des [expressions](src/fr/petitjava/nodes/expressions/ExpressionNode.java).
Timothé Rosaz's avatar
Timothé Rosaz committed
88
Il s'agit une brique du code, comme une référence à un objet, un appel à une méthode ou autre. À cette étape-là du programme, on ne se préoccupe pas de mla cohérence des types.
89
90
La cohérence syntaxique suffit. Par exemple, une condition doit être de la forme `if(<EXPRESSION>) <CONTENU> [else <STATEMENT>]`.

Timothé Rosaz's avatar
Timothé Rosaz committed
91
Tout ce processus est dirigé par la classe "statique" [Parser](src/fr/petitjava/Parser.java), mais en général la création d'une certaine instance
92
est laissée à la classe en question (par des méthodes statiques `$generate()`).
Timothé Rosaz's avatar
Timothé Rosaz committed
93
Certains cas particuliers comme le traitement des expressions mathématiques ou logiques sont traitées différemment du reste.
94
95
96
97
Et notons que la différence entre la concaténation de Strings et les calculs sont effectuées dans l'étape suivante.

### 3. Validation de type

Timothé Rosaz's avatar
Timothé Rosaz committed
98
Le Java est, pour notre plus grand plaisir, statiquement et explicitement typé. Ainsi, les variables dans un statement n'ont que trois sources possibles :
Timothé Rosaz's avatar
Timothé Rosaz committed
99
un champ associé à la classe ou à l'instance, un paramètre de la méthode en question ou une variable déclarée précédemment dans la méthode. Dans tous les
100
101
102
103
cas, le type est spécifié avant le nom, donc savoir de quel type est une variable et vérifier la cohérence entre les statement dans l'ordre du code est aisé.

C'est aussi durant cette étape que l'on cherche une méthode main, que l'on vérifie les retours des méthodes et que l'on vérifie les propriétés héritées.

Timothé Rosaz's avatar
Timothé Rosaz committed
104
Chaque nœud de l'arbre précédemment établit possède une méthode `#validateType(TypeContext)`, ce qui permet des appels récursifs au sein de la structure.
Timothé Rosaz's avatar
Timothé Rosaz committed
105
La classe dirigeant ces évènements, comme dans les cas précédents, le fait depuis sa propre classe [TypeValidation](src/fr/petitjava/TypeValidation.java).
106
107
108
109
110
111

### 4. Transpilation

Maintenant que notre arbre a été vérifié comme étant valide du point de vue typage et syntaxique, il faut le transformer en chaines de caractères.
Pour ce faire, nous avons implémenté le patron de conception du [visiteur](https://fr.wikipedia.org/wiki/Visiteur_(patron_de_conception)).
Cela nous semblait être la meilleure solution dans un contexte de programmation objet. Ainsi, tout le code concernant cette transpilation
Timothé Rosaz's avatar
Timothé Rosaz committed
112
se situe dans la classe [VisiteurC](src/fr/petitjava/compilers/VisiteurC.java) qui implémente l'interface [Visiteur](src/fr/petitjava/compilers/Visiteur.java).
113
114
115
116

### Notes additionnelles

Le but étant de concevoir ce projet comme étant un projet de long terme, nous avons mis en place des systèmes assez généraux
Timothé Rosaz's avatar
Timothé Rosaz committed
117
comme toute la [fake STD](src/fr/petitjava/std) ou un début de ["système d'imports"](src/fr/petitjava/compilers/NativeHandler.java).
Timothé Rosaz's avatar
Timothé Rosaz committed
118
119
120

Pour le système d'erreur, je me suis aidé de [Wikipédia](https://en.wikipedia.org/wiki/Setjmp.h) tout simplement. J'ai ensuite rajouté
quelques `define` pour éviter d'avoir du code impossible a débugger. Notons tout de même que ce rajout est à la
121
limite de ce qui est acceptable d'un point de vue code.