Description de l'étape

Vous devez écrire un vérificateur de types, conforme aux règles de validité du typage de Drei.

Structures de données

Analyseur de types

L'analyseur de types va vérifier que toutes les prémisses des règles d'inférences sont correctes (dérivable en des axiomes) sur le programme analysé. A partir de la règle «Program», l'analyseur procédera à une descente récursive à travers l'AST, guidé par les règles de typage, jusqu'à atteindre des axiomes. Si l'une ou l'autre règle ne peut vérifier ses prémisses, une erreur sera générée (mais n'oubliez pas que l'analyse doit continuer quand même).

Attention toutefois.

Cela n'est pas un problème dans la définition formelle du système de type: la notion d'ordre d'exécution n'y est pas définie. Vous devrez donc contourner ce problème en cachant le fait que votre analyseur s'exécute d'après un ordre bien défini.

La solution la plus simple est de diviser votre analyse en trois «tranches» distinctes.

  1. L'introduction des symboles de classes dans la portée des classes, et la définition de la super-classe éventuelle (notez ici qu'une classe ne peut pas étendre une classe définie après elle).
  2. L'introduction des symboles des membres dans la portées des membres de chaque classe.
  3. La validation du corps des méthodes.

Vous constaterez que la séparation se fait au niveau des règles «Program», «Class1», «Class2» et «Method» chaque tranche vérifiant une partie des prémisses.

Les plus téméraires (et eux seuls) pourront essayer d'implanter l'algorithme avec des valeurs gelées (lazy) plutôt que des tranches.

Définissez l'analyseur comme une classe avec l'interface suivante.

class Analyzer {
  def analyzeProgram(tree: Program): Unit
}
analyzeProgram
Un méthode qui analyse l'AST tree. Cette méthode retourne toujours, mais génère en effet de bord une liste des erreurs de types détectées dans l'AST.

Vous aurez intérêt à définir d'autres méthodes analyze…(…), au moins pour chaque catégorie de règles de typage (programmes, membres, expressions, etc.). Inspirez-vous de la «forme» de ces catégories de règles pour définir les paramètres de ces méthodes.

Un canevas pour cette classe est à votre disposition.

Soyez attentif à la difficulté qu'il y a à implanter l'entier du système de type en une seule étape. Préférez une approche modulaire: implantez un sous-ensemble minimal des règles (permettant la définition des classes et champs, par exemple, similaire au contenu du cours «analyse de noms») et testez celles-ci. Ajoutez ensuite les règles les unes après les autres, en testant à chaque étape.

Notez bien que vos programmes devront dorénavant être correctement typés pour êtres acceptés par votre compilateur. En particulier, les chaînes de caractères ne pourront êtres acceptées que si des classes définissant les listes existent. Une implantation des listes en Drei est à votre disposition.

Autres classes de support

AnalyzerTest.scala
Cet objet permet de tester votre analyseur de types, à condition que l'interface de celui-ci corresponde. A l'exécution
  • son premier paramètre est le fichier source du programme à analyser,
  • son second paramètre, optionnel, est le fichier de destination pour l'impression du résultat.