L'objectif de ce TP est d'étendre le langage A6000 avec des mécanismes de gestion des exceptions. On introduira deux opérations de base :

1. Description

1.1. Extension du langage source

1.1.1. Lexique

Le langage contient les nouveaux mots-clés throw, try et catch.

1.1.2. Grammaire

La grammaire des instructions est étendue de deux nouvelles productions pour le déclenchement et le rattrapage d'exceptions.

      [instruction] ← ...
		    |  throw
		    |  try ( [instructions] ) catch ( [instructions] )

1.1.3. Sémantique

L'exécution d'une instruction throw déclenche une exception, qui interrompt le cours normal de l'exécution : soit l'exécution s'arrête immédiatement, soit l'exécution reprend au niveau d'un code de rattrapage introduit par catch.

L'exécution d'une instruction try (b₁) catch (b₂) commence par l'exécution de b₁.

Remarque : dans cette version de base, on ne distingue pas entre différentes exceptions.

1.2. Extension du compilateur

1.2.1. Conventions

On suivra une stratégie dite de stack cutting, dans laquelle le tas contient un ensemble de gestionnaires d'exceptions correspondant chacun à une construction try/catch en cours d'exécution, les différents gestionnaires étant chaînés entre eux, du plus récent vers le plus ancien.

Un gestionnaire est un bloc dans le tas avec au moins deux champs utiles, contenant l'adresse du code du bloc catch associé et l'adresse du gestionnaire précédent.

    --|-----------|--
      |           |
      |    ...    |      <- infos additionnelles éventuelles
      |           |
      |-----------|
      |   Catch   |      <- pointeur de code de rattrapage
      |-----------|
      |   Prec    |      <- bloc du gestionnaire précédent
      |-----------|
      |  En-tête  |
    --|-----------|--

On réserve l'un des registres (par exemple gp) pour enregistrer l'adresse du gestionnaire courant (c'est-à-dire le plus récent).

Détail du protocole :

1.2.2. Syntaxes abstraites

Dans la syntaxe abstraite source SourceAst, on étend le type instruction avec deux constructeurs Throw et Try of block * block.

À partir de l'étape GotoAst, le constructeur Try est remplacé par deux constructeurs NewHandler of label et RmHandler qui correspondent respectivement à la création d'un nouveau gestionnaire d'exception (lors de l'entrée dans le bloc try) et à l'abandon du dernier gestionnaire (lors de la sortie avec succès d'un bloc try ou d'un bloc catch).

2. Travail à effectuer

Vous devez étendre l'ensemble du compilateur pour intégrer ces nouveaux mécanismes.

3. Extensions

3.1. Déclaration et analyse des exceptions

Modifier la syntaxe de déclaration des fonctions pour permettre d'annoter une fonction susceptible de propager une exception, que ce soit car elle déclenche elle-même une exception qu'elle ne rattrape pas, ou car elle fait appel sans précautions à une autre fonction susceptible de propager une exception, à la manière de ce qui est fait en Java.

Ajouter vers le début du processus de compilation (par exemple sur la syntaxe SourceAst) une analyse vérifiant que chaque fonction susceptible de propager une exception non rattrapée est bien annotée comme telle.

Remarque : avec des fonctions récursives, cette analyse pourra demander de calculer un point fixe, ainsi qu'il était fait dans le TP 3 avec les équations de flot de données.

3.2. Exceptions distinguées

Enrichir la syntaxe pour permettre la distinction entre plusieurs exceptions, par exemple caractérisées par des nombres entiers.

Une instruction throw doit dans ce cas préciser l'exception qui est déclenchée, et un bloc try peut être associé à plusieurs blocs catch, chacun associé à une exception. Lorsqu'une exception est déclenchée, on regarde d'abord si elle est rattrapée par l'un des catch du gestionnaire courant, et à défaut on propage au gestionnaire précédent.

3.3. Exceptions paramétrées

Enrichier la syntaxe pour permettre d'associer une valeur à une exception, qui sera transmise au bloc catch.

Dans ce cas, la valeur peut être transmise via une case du bloc du gestionnaire d'exception courant, et le code du bloc catch peut faire appel à une variable spéciale liée à l'adresse de cette case.