Previous Up Next

Chapter 5  Contrôle de type

Il existe deux contrôles de type. Le contrôle de type statique qui analyse l'arbre de syntaxe abstraite (ASA) notamment pour rechercher les éventuelles incompatibilités de type entre les opérandes, avant que celui-ci ne soit parcouru par le module de compilation. Le contrôle de type dynamique qui collabore avec l'interpréteur lors de l'exécution du code, pour éviter les débordements de pile ou l'adressage de parcelles de mémoire non allouées. Seul le contrôle de type statique a été mis en place dans le cadre de ce projet.

5.1  Idée générale

Le contrôle de type intervient dans le cadre de l'analyse sémantique du programme. Pendant cette phase, on effectue un certain nombre de tests sur l'arbre de syntaxe abstraite (ASA) afin d'examiner si l'assemblage des constituants du programme a un sens. Afin d'explorer l'ASA, nous utilisons le paradigme de programmation  visiteur . Au fur et à mesure du parcours, nous réalisons certaines opérations ayant pour but de construire une table des symboles et de contrôler le type des noeuds.

5.2  Réalisation

5.2.1  Choix des structures de données

Le module contrôle de type doit stocker deux types d'informations : la table des symboles et la liste des méthodes d'une part, une liste des différentes incohérences rencontrées pendant son exécution d'autre part. L'emploi du type Vector proposé par Java est parfaitement adapté puisque son utilisation se rapproche de celle des tableaux, tout en proposant une taille variable.

5.2.2  Utilisation du paradigme de programmation  Visiteur 

Dans le module contrôle de type, une chaîne de caractères est retournée par le visiteur  lorsque celui-ci visite un noeud. Par exemple, le  visiteur  retourne la chaîne de caractères  booleen lorsqu'il est dans le noeud = (ASTegal), si les deux fils du noeud sont du même type. Lorsque les fils du noe ud sont des feuilles, on consulte la table des symboles pour vérifier d'une part si les symboles ont bien été déclarés, et d'autre part, si leurs types concordent avec ce que le noeud exige. Les différentes chaînes retournées sont les suivantes : Exemple : le visiteur du noeud Si
public Object visit(ASTsi node, Object data){
        
  String typNoeud1=null;  // Type du premier noeud
  String typNoeud2=null;  // Type du second noeud
  boolean err=false;      // booleen qui passe à false si il y a une erreur
  String retour;          // Chaine de caractere retournée par le noeud
  boolean trouve;         /* booléen qui passe à true, si la 
                             variable,constante a été trouvée */
  
  // On récupère le type du premier noeud
  typNoeud1=(String) node.jjtGetChild(0).jjtAccept(this,data);
  
  // Si typNoeud1==null, le premier noeud est une feuille
  if (typNoeud1==null) {
    
    // On récupère le nom de la feuille
    String noeud1=new String(node.jjtGetChild(0).toString());
    
    // On regarde si le nom correspond à une variable
    trouve=chercherVar(noeud1,node.getLigne());
    
    if(trouve){
      // Si c'est le cas, on recupère le type de la variable
      typNoeud1=getTypeVar(node.jjtGetChild(0).toString());
    } else {
      // Sinon, on regarde si le nom correspond à une constante
      trouve=chercherTab(noeud1,node.getLigne());
      
      if(trouve){
        // Si c'est le cas, on récupère le type de la constante
        typNoeud1=getTypeTab(node.jjtGetChild(0).toString());
      } else {
        // Sinon, on ajoute le nom de la feuille comme étant non déclaré
        ajouteNonDeclare(node.jjtGetChild(0).toString(),node.getLigne());
      }
    }
  }

  // Si le 1er noeud n'a pas de type (feuille non déclarée)
  if(typNoeud1==null){
    err=true;
    // On ajoute une erreur
    erreur e1 = new erreur(TYPE_INCORRECT,
                           "if : booleen attendu",
                           node.getLigne());
    listeErreur.addElement(e1);
  } else {
    // Si le 1er noeud n'est pas de type booléen
    if(typNoeud1.compareTo("booleen")!=0){
      err=true;
      // On ajoute aussi une erreur
      erreur e2 = new erreur(TYPE_INCORRECT,
                             "if : booleen attendu",
                             node.getLigne());
      listeErreur.addElement(e2);
    }
  }
  
  // On recupère le second noeud
  typNoeud2=((String) node.jjtGetChild(1).jjtAccept(this,data));
  if(typNoeud1==null){
    err=true;
  } else {
    // On vérifie qu'il s'agit bien d'un noeud d'instruction
    if(typNoeud1.compareTo("ok")!=0){
      err=true;
    }
  }

  // Si tout est OK, on renvoie "ok", "erreur" dans les autres cas
  if(err==true){
    retour=new String("erreur");
  } else {
    retour=new String("ok");
  }
  
  return retour;
}

5.2.3  Gestion des variables

Portée des variables

Lorsque le visiteur   rencontre des noeuds correspondant à des déclarations, il met à jour la table des symboles mais aussi l'ASA. En effet pour prendre en compte la portée des variables, on renomme les variables de cette façon :
Variable globale
: la variable a devient globalea.
Variable locale à la fonction test
: la variable a devient testa.

Table des symboles

On utilise trois Vector Java pour représenter la table des symboles.
listeVar
contient les variables.
listeTab
contient les tableaux.
listeCst
contient les constantes.
Chacun de ces Vector contient deux chaînes de caractères par enregistrement, le type du symbole et le nom de celui-ci.

5.2.4  Table des méthodes

Là aussi on utilise un Vector : listeMethode. Il sert à enregistrer les différentes fonctions déclarées. Le type de retour, le nom, puis les types des paramètres de la fonction sont enregistrés dans un premier vecteur. Ce vecteur sera ensuite ajouté dans listeMethode.


Figure 5.1: Le vecteur listeMethode


Lors des appels de fonction, on parcourt listeMethode pour trouver les informations inhérentes à la fonction et ainsi vérifier la pertinence des appels.

5.2.5  Les erreurs

Lorsque le module rencontre des incohérences sémantiques dans l'ASA, il crée une nouvelle erreur. La structure erreur est composée de trois champs :

5.3  Jeux de test

Voici la liste des tests effectués sur le module contrôle de type : Tests sur la portée des variables : Test concernant la table des symboles : Tests sur l'incompatibilité de type des opérandes : Tests sur les instructions : Tests sur les fonctions :
Previous Up Next