diff --git a/rapport.md b/rapport.md index ee294e8..7f72822 100644 --- a/rapport.md +++ b/rapport.md @@ -11,6 +11,7 @@ Le but de ce projet est d'ajouter différentes fonctionnalités au langage RAT. Pour chacune de ses implantations, il a fallut modiffier les codes correspondants aux différentes étapes de la compilation. La modification du `lexer` (pour reconnaitre les nouveaux mots), le parser (pour reconnaitre la nouvelle grammaire) et les différentes passes pour vérifier la cohérence sémantique du code RAT à compiler. ## Modifications générales de l'AST + Lors de l'ajout des différentes extensions, nous avons évidement du modifier l'AST pour l'adapter aux différents ajouts. Le plus gros ajout, qui est commun a plusieurs extensions, est l'affectable. L'affect, comme son nom l'indique, va désigner un objet pouvant être affecté. Avant l'ajout des différentes expression, il n'y avait que les identificateurs qui pouvaient faire office d'affectbale mais maintenant, il y a les `dref`, les `attribut` d'un objet de type `struct` ou encore les identifiants. De plus, pour chaque nouveau type, il a fallu ajouter dans l'AST de la passe typage, dans les instructions, un type print tel que `printStruct` pour les structs. @@ -19,4 +20,19 @@ De plus, pour chaque nouveau type, il a fallu ajouter dans l'AST de la passe typ L'implenation des pointeurs a commencé par l'ajout du type `Pointeur of typ`. Ainsi, le type pointeur reste assez abstrait pour pouvoir ajouter des types sans avoir a modifier du code au niveau des pointeurs. De plus, cette implentation permet de construire des "pointeurs de pointeurs". \ En ce qui concerne les modifications de l'AST, nous avons ajouté la `dref` pour l'affectable. Les nouvelles expressions apportés sont `Null`, `NewType` et `Adresse`. \ Les modifications apportées à la passe TDS est l'utilisation que de `dref` et d'`Adresse` doit être utilisé sur des identifiants déjà existant. Dans le cas contraire, une exception d'utilisation d'identifiant est levé. \ -Le plus gros du travail pour les pointeurs a été réalisé sur la passe de typage. En effet, cette passe doit vérifier que les objets sont typement compatibles. L'expression `Null` est \ No newline at end of file +Le plus gros du travail pour les pointeurs a été réalisé sur la passe de typage. En effet, cette passe doit vérifier que les objets sont typement compatibles. L'expression `Null` est + +## Incrémentation + +Cette fonctionnalité est très simple à implémenter, on remplace simplement toutes les instances de `a += b` par `a = a + b`. +On a ainsi dans `parler.mly` +``` +| aff=a PLUS EQUAL exp=e PV {Affectation (aff, Binaire (Plus, Affectable(aff), exp))} +``` + +## Type nommé + + + +## Structure + diff --git a/src/passeCodeRatToTam.ml b/src/passeCodeRatToTam.ml index 7e78c15..1ee17cf 100644 --- a/src/passeCodeRatToTam.ml +++ b/src/passeCodeRatToTam.ml @@ -11,9 +11,21 @@ struct type t1 = Ast.AstPlacement.programme type t2 = string +(* + getTailleAvant: + affectable -> t2 -> int + Description: + Avoir la taille avant l'attribut n dans un struct + Parameters: + - aff : affectable de type struct + - n : nom de l'attribut + Returns: + La taille prise par les attribut avant n +*) let rec getTailleAvant aff n = match aff with | Dref(aff2, _) -> getTailleAvant aff2 n + | Ident(info) -> begin match info_ast_to_info info with @@ -28,6 +40,7 @@ let rec getTailleAvant aff n = in tai | _ -> failwith "Internal Error" end + | Attribut(aff2, info) -> begin match info_ast_to_info info with @@ -38,15 +51,27 @@ let rec getTailleAvant aff n = | _ -> failwith "Internal Error" end +(* + getType: + affectable -> typ + Description: + Avoir le type d'un affectable + Parameters: + - aff : affectable dont on veut avoir le type + Returns: + Le type de l'affectable +*) and getType aff = match aff with | Dref(aff2, _) -> getType aff2 + | Ident(info) -> begin match info_ast_to_info info with | InfoVar(_, t, _, _) -> t | _ -> failwith "Internal Error" end + | Attribut(aff2, info) -> begin match info_ast_to_info info with @@ -67,9 +92,21 @@ and getType aff = | _ -> failwith "Internal Error" end +(* + getTailleAttribut: + affectable -> t2 -> int + Description: + Avoir la taille d'un attribut d'un affectable de type struct + Parameters: + - aff : affectable de l'attribut + - n : nom de l'attribut + Returns: + La taille de l'attribut +*) and getTailleAttribut aff n = match aff with | Dref(aff2, _) -> getTailleAttribut aff2 n + | Ident(info) -> begin match info_ast_to_info info with @@ -83,17 +120,30 @@ and getTailleAttribut aff n = ) l_typstr 0 | _ -> failwith "Internal Error" end + | Attribut(_, _) -> getTaille (getType aff) +(* + getBase: + affectable -> int + Description: + Avoir la base d'un affectable + Parameters: + - aff : affectable dont on veut avoir la base + Returns: + La base de l'affectable +*) and getBase aff = match aff with | Dref (a,_) -> getBase a + | Ident(i) -> begin match info_ast_to_info i with | InfoVar(_, _, base, _) -> base | _ -> failwith "Internal Error" end + | Attribut(a,i) -> begin match info_ast_to_info i with @@ -105,24 +155,55 @@ and getBase aff = | _ -> failwith "Internal Error" end +(* + getBase: + affectable -> t2 + Description: + Avoir le registre d'un affectable + Parameters: + - aff : affectable dont on veut avoir le registre + Returns: + Le registre de l'affectable +*) and getReg aff = match aff with | Dref (a,_) -> getReg a + | Ident(i) -> begin match info_ast_to_info i with | InfoVar(_, _, _, reg) -> reg | _ -> failwith "Internal Error" end + | Attribut(a,_) -> getReg a +(* + extraction_info: + affectable -> info_ast + Description: + Avoir l'info d'un affectable + Parameters: + - aff : affectable dont on veut avoir l'info + Returns: + L'info de l'affectable +*) and extraction_info aff = match aff with | Dref(aff2, _) -> extraction_info aff2 | Ident(info) -> info | Attribut(aff2, _) -> extraction_info aff2 - +(* + analyse_code_affectable: + affectable -> t2 + Description: + Convertir un affectable en code TAM + Parameters: + - aff : affectable que l'on veut convertir + Returns: + Le code TAM de l'affectable +*) and analyse_code_affectable a = match a with | Dref(aff, t) -> @@ -142,6 +223,16 @@ and analyse_code_affectable a = let reg = getReg a in "LOAD (" ^ (string_of_int (getTaille (getType a))) ^ ") " ^ (string_of_int (base)) ^ "[" ^ reg ^ "]\n" +(* + analyse_code_expression: + expression -> t2 + Description: + Convertir une expression en code TAM + Parameters: + - e : expression que l'on veut convertir + Returns: + Le code TAM correspondant +*) and analyse_code_expression e = match e with | AppelFonction(i, le) -> @@ -204,6 +295,19 @@ and analyse_code_expression e = | Nothing -> "" +(* + analyse_code_instruction: + instruction -> t2 -> t2 -> t2 -> t2 + Description: + Convertir une instruction en code TAM + Parameters: + - i : instruction que l'on veut ecrire en TAM + - taille_return : taille du retour si on est dans une fonction + - taille_args : taille des arguments si on est dans une fonction + - taille_var : taille des varibales local a une fonction ou a un bloc + Returns: + Le code TAM correpondant à l'instruction +*) and analyse_code_instruction i taille_return taille_args taille_var = match i with | Declaration(i, e) -> @@ -268,7 +372,6 @@ and analyse_code_instruction i taille_return taille_args taille_var = "SUBR IOut\n" | AffichageStruct(e, t) -> - let rec affichage base reg t0 = match t0 with | Struct(l_typstr) -> @@ -284,6 +387,7 @@ and analyse_code_instruction i taille_return taille_args taille_var = "LOADL ' '\n" ^ "SUBR COut\n" ,taille + (getTaille t)) + | Int -> ( res ^ "LOAD (" ^ (string_of_int (getTaille t)) ^ ") " ^ (string_of_int taille) ^ "[" ^ reg ^ "]\n" ^ @@ -291,6 +395,7 @@ and analyse_code_instruction i taille_return taille_args taille_var = "LOADL ' '\n" ^ "SUBR COut\n" ,taille + (getTaille t)) + | Rat -> ( res ^ "LOAD (" ^ (string_of_int (getTaille t)) ^ ") " ^ (string_of_int taille) ^ "[" ^ reg ^ "]\n" ^ @@ -298,6 +403,7 @@ and analyse_code_instruction i taille_return taille_args taille_var = "LOADL ' '\n" ^ "SUBR COut\n" ,taille + (getTaille t)) + | Pointeur(_) -> ( res ^ "LOADL '@'\n" ^ @@ -307,6 +413,7 @@ and analyse_code_instruction i taille_return taille_args taille_var = "LOADL ' '\n" ^ "SUBR COut\n" ,taille + (getTaille t)) + | Struct(_) -> ( res ^ "LOADL '{'\n" ^ @@ -317,7 +424,9 @@ and analyse_code_instruction i taille_return taille_args taille_var = "LOADL ' '\n" ^ "SUBR COut\n" ,taille + (getTaille t)) + | _ -> failwith "Internal Error" + ) ("LOADL ' '\nSUBR COut\n", base) l_t in res end @@ -354,6 +463,7 @@ and analyse_code_instruction i taille_return taille_args taille_var = begin match a with | Dref(_, _) -> failwith "Internal Error" + | Ident(i) -> begin match info_ast_to_info i with @@ -361,6 +471,7 @@ and analyse_code_instruction i taille_return taille_args taille_var = affichage base reg t | _ -> failwith "Internal Error" end + | Attribut(_, i) -> match info_ast_to_info i with | InfoVar(_, t, _, _) -> @@ -369,6 +480,7 @@ and analyse_code_instruction i taille_return taille_args taille_var = affichage base reg t | _ -> failwith "Internal Error" end + | AppelFonction(i, le) -> begin match info_ast_to_info i with @@ -380,22 +492,6 @@ and analyse_code_instruction i taille_return taille_args taille_var = "CALL (ST) " ^ nom ^ "\n" ^ (affichage base reg t) ^ "POP (0) " ^ (string_of_int (getTaille t)) ^ "\n" - (* List.fold_right ( - fun (t, _) res -> - let i = - match t with - | Bool -> AffichageBool(Nothing) - | Int -> AffichageInt(Nothing) - | Rat -> AffichageRat(Nothing) - | Pointeur(_) -> AffichagePointeur(Nothing) - | Struct(l_ts) -> AffichageStruct(Tuple(List.map (fun _ -> Nothing) l_ts), t) - | _ -> failwith "Internal Error" - in - "LOADL ' '\n" ^ - "SUBR COut\n" ^ - (analyse_code_instruction i "0" "0" "0") ^ - res - ) l_typstr "LOADL ' '\nSUBR COut\n" *) | _ -> failwith "Internal Error" end | _ -> failwith "Internal Error" @@ -435,6 +531,18 @@ and analyse_code_instruction i taille_return taille_args taille_var = | Empty -> "" +(* + analyse_code_bloc: + bloc -> t2 -> t2 -> t2 + Description: + Convertir un bloc en code TAM + Parameters: + - bloc : bloc que l'on veut ecrire en TAM + - taille_return : taille du retour si on est dans une fonction + - taille_args : taille des arguments si on est dans une fonction + Returns: + Le code TAM correpondant au bloc +*) and analyse_code_bloc bloc taille_return taille_args = let taille_var = string_of_int (List.fold_right (fun e res -> taille_variables_declarees e + res) bloc 0) in List.fold_right ( @@ -442,6 +550,16 @@ and analyse_code_bloc bloc taille_return taille_args = ) bloc "" ^ "POP (0) " ^ taille_var ^ "\n" +(* + analyse_code_fonction: + fonction -> t2 -> t2 -> t2 + Description: + Convertir une fonction en code TAM + Parameters: + - fonction : fonction à convertir + Returns: + Le code TAM de la fonction +*) and analyse_code_fonction (AstPlacement.Fonction(info, _, bloc)) = match info_ast_to_info info with | InfoFun(name, t, l_t) -> @@ -453,6 +571,16 @@ and analyse_code_fonction (AstPlacement.Fonction(info, _, bloc)) = | _ -> failwith "Internal Error" +(* + analyse_code_fonction: + prgramme -> t2 + Description: + Convertir un programme en code TAM + Parameters: + - programme : programme à convertir + Returns: + Le code TAM du programme +*) let analyser (AstPlacement.Programme(fonctions, prog)) = let code = getEntete () in let code = code ^ List.fold_right (fun e res -> (analyse_code_fonction e) ^ res) fonctions "" in diff --git a/src/passePlacementRat.ml b/src/passePlacementRat.ml index 9e58bb4..36cf1f9 100644 --- a/src/passePlacementRat.ml +++ b/src/passePlacementRat.ml @@ -11,6 +11,18 @@ struct type t2 = Ast.AstPlacement.programme +(* + analyse_placement_instruction: + instruction -> int -> string -> int + Description: + Modifie le placement des info (base et registre) et retourne le nombre de place prise + Parameters: + - i : l'instruction à analyser + - base : la base actuel + - reg : le registre actuel + Returns: + La place prise par l'instruction +*) let rec analyse_placement_instruction i base reg = match i with | AstType.Declaration(info, _) -> @@ -34,6 +46,19 @@ let rec analyse_placement_instruction i base reg = | _ -> 0 + +(* + analyse_placement_bloc: + int -> string -> AstType.bloc -> int + Description: + Analyse le bloc instruction par instruction (base et registre) et retourne le nombre de place prise par le bloc + Parameters: + - base : la base actuel + - reg : le registre actuel + - bloc : bloc à analyser + Returns: + La place prise en mémoire par le bloc +*) and analyse_placement_bloc base reg bloc = match bloc with | [] -> base @@ -41,6 +66,17 @@ and analyse_placement_bloc base reg bloc = let taille = analyse_placement_instruction t base reg in analyse_placement_bloc (base + taille) reg q + +(* + analyse_placement_fonction: + AstType.fonction -> AstPlacement.fonction + Description: + Analyse le placement d'une fonction + Parameters: + - fonction : La fonction à analyser + Returns: + La fonction analysée +*) and analyse_placement_fonction (AstType.Fonction(info, l_typinfo, bloc)) = let _ = List.fold_right (fun x res_q -> begin @@ -51,9 +87,22 @@ and analyse_placement_fonction (AstType.Fonction(info, l_typinfo, bloc)) = | _ -> failwith "Internal Error" end ) l_typinfo 0 in + + (* Avec les 3 places prises par l'enregistrement d'activation, l'analyse du bloc commence à 3 *) let _ = analyse_placement_bloc 3 "LB" bloc in Fonction(info, l_typinfo, bloc) + +(* + analyser: + AstType -> AstPlacement + Description: + Analyser un programme + Parameters: + - programme : Le programme à analyser + Returns: + Le programme analysée +*) let analyser (AstType.Programme(fonctions, prog)) = let n_fonctions = List.map analyse_placement_fonction fonctions in let _ = analyse_placement_bloc 0 "SB" prog in diff --git a/src/passeTdsRat.ml b/src/passeTdsRat.ml index 2b75bc3..2198f7f 100644 --- a/src/passeTdsRat.ml +++ b/src/passeTdsRat.ml @@ -11,6 +11,7 @@ struct type t1 = Ast.AstSyntax.programme type t2 = Ast.AstTds.programme + (* recherche_type: tds -> typ -> typ @@ -21,10 +22,6 @@ struct - t : le type que l'on cherche Returns: Le type d'un typedef - Pre-conditions: - - True - Post-conditions: - - True Exceptions: - IdentifiantNonDeclare *) @@ -46,6 +43,7 @@ let rec recherche_type tds t = Struct n_l_typstr | _ -> t + (* analyse_tds_affectable: tds -> AstSyntax.affectable -> bool -> AstTds.affectable @@ -57,10 +55,6 @@ let rec recherche_type tds t = - modif : permet de savoir s'il sagit d'un affectable dans une expression ou dans une affectation Returns: Un nouvel AstTds.affectable - Pre-conditions: - - True - Post-conditions: - - True Exceptions: - IdentifiantNonDeclare - MauvaiseUtilisationIdentifiant @@ -102,10 +96,6 @@ let rec analyse_tds_affectable tds a modif = - aff : Affectable dont on veut extraire l'info Returns: L'info de l'affectable - Pre-conditions: - - True - Post-conditions: - - True *) let rec extraction_info aff = match aff with @@ -124,13 +114,14 @@ let rec analyse_tds_affectable tds a modif = let t = List.fold_right (fun (t, n) res -> if str = n then t else res) l_att Undefined in if t != Undefined then AstTds.Attribut(n_aff, info_to_info_ast (InfoVar(str, t, 0, ""))) - else (** L'attribut ne correspond à aucun attribut du struct *) + else (* L'attribut ne correspond à aucun attribut du struct *) raise (MauvaiseUtilisationIdentifiant str) - | _ -> (** Il faut que l'objet sur le quel on appelle l'attribut soit un struct *) + | _ -> (* Il faut que l'objet sur le quel on appelle l'attribut soit un struct *) raise (MauvaiseUtilisationIdentifiant str) - end (** Ce ne peut etre qu'un InfoVar *) + end (* Ce ne peut etre qu'un InfoVar *) | _ -> raise (MauvaiseUtilisationIdentifiant str) + (* analyse_tds_affectable: tds -> AstSyntax.expression -> AstTds.expression @@ -141,10 +132,6 @@ let rec analyse_tds_affectable tds a modif = - e : l'expression à analyser Returns: Une nouvelle AstTds.expression - Pre-conditions: - - True - Post-conditions: - - True Exceptions: - IdentifiantNonDeclare - MauvaiseUtilisationIdentifiant @@ -216,10 +203,6 @@ let rec analyse_tds_expression tds e = - td : le typedef à analyser Returns: Une nouvelle AstTds.affectable - Pre-conditions: - - True - Post-conditions: - - True Exceptions: - DoubleDeclaration *) @@ -234,28 +217,21 @@ let analyse_tds_typedef tds (AstSyntax.TypeDef(n, t)) = raise (DoubleDeclaration n) end -(* analyse_tds_instruction : AstSyntax.instruction -> tds -> AstTds.instruction *) -(* Paramètre tds : la table des symboles courante *) -(* Paramètre i : l'instruction à analyser *) -(* Vérifie la bonne utilisation des identifiants et tranforme l'instruction -en une instruction de type AstTds.instruction *) -(* Erreur si mauvaise utilisation des identifiants *) + (* - analyse_tds_typedef: - tds -> AstSyntax.typedef -> AstTds.instruction + analyse_tds_instruction: + tds -> AstSyntax.instruction -> AstTds.instruction Description: - Transforme les typedef de l'AstSyntax en AstTds.instructions + Vérifie la bonne utilisation des identifiants et tranforme l'instruction en une instruction de type AstTds.instruction Parameters: - tds : la table des symboles courante - - td : le typedef à analyser + - i : l'instruction à analyser Returns: - Une nouvelle AstTds.affectable - Pre-conditions: - - True - Post-conditions: - - True + Une nouvelle AstTds.instruction Exceptions: - DoubleDeclaration + - IdentifiantNonDeclare + - MauvaiseUtilisationIdentifiant *) let rec analyse_tds_instruction tds i = match i with @@ -366,39 +342,48 @@ let rec analyse_tds_instruction tds i = (* Analyse du typedef *) analyse_tds_typedef tds td - -(* analyse_tds_bloc : AstSyntax.bloc -> AstTds.bloc *) -(* Paramètre tds : la table des symboles courante *) -(* Paramètre li : liste d'instructions à analyser *) -(* Vérifie la bonne utilisation des identifiants et tranforme le bloc -en un bloc de type AstTds.bloc *) -(* Erreur si mauvaise utilisation des identifiants *) -and analyse_tds_bloc tds li = - (* Entrée dans un nouveau bloc, donc création d'une nouvelle tds locale - pointant sur la table du bloc parent *) - let tdsbloc = creerTDSFille tds in - (* Analyse des instructions du bloc avec la tds du nouveau bloc - Cette tds est modifiée par effet de bord *) - let nli = List.map (analyse_tds_instruction tdsbloc) li in - (* afficher_locale tdsbloc ; *) (* décommenter pour afficher la table locale *) - nli - -(* analyse_tds_fonction : AstSyntax.fonction -> AstTds.fonction *) -(* Paramètre tds : la table des symboles courante *) -(* Paramètre : la fonction à analyser *) -(* Vérifie la bonne utilisation des identifiants et tranforme la fonction -en une fonction de type AstTds.fonction *) -(* Erreur si mauvaise utilisation des identifiants *) (* - tds -> - AstSyntax.fonction[typ * string * (typ * string) list * bloc] -> - AstTds.fonction[typ * Tds.info_ast * (typ * Tds.info_ast ) list * bloc] + analyse_tds_bloc: + tds -> AstSyntax.bloc -> AstTds.bloc + Description: + Vérifie la bonne utilisation des identifiants et tranforme le bloc en un bloc de type AstTds.bloc + Parameters: + - tds : la table des symboles courante + - li : la liste d'instructions (bloc) à analyser + Returns: + Un nouvel AstTds.bloc +*) +and analyse_tds_bloc tds li = + (* Entrée dans un nouveau bloc, donc création d'une nouvelle tds locale pointant sur la table du bloc parent *) + let tdsbloc = creerTDSFille tds in + + (* Analyse des instructions du bloc avec la tds du nouveau bloc, cette tds est modifiée par effet de bord *) + let nli = List.map (analyse_tds_instruction tdsbloc) li in + + (* afficher_locale tdsbloc ; *) (* décommenter pour afficher la table locale *) + nli + + +(* + analyse_tds_fonction: + tds -> AstSyntax.fonction -> AstTds.fonction + Description: + Vérifie la bonne utilisation des identifiants et tranforme la fonction en une fonction de type AstTds.fonction + Parameters: + - maintds : la table des symboles courante + - f : la fonction à analyser + Returns: + Une nouvelle AstTds.instruction + Exceptions: + - DoubleDeclaration *) let analyse_tds_fonction maintds (AstSyntax.Fonction(t, str, l_typstr, bloc)) = begin match chercherLocalement maintds str with - | Some _ -> raise (DoubleDeclaration str) + | Some _ -> (* L'identifiant est trouvé dans la tds locale, il a donc déjà été déclaré dans le bloc courant *) + raise (DoubleDeclaration str) + | None -> begin (* Copie de la tds globale dans la tds locale au bloc *) @@ -436,11 +421,17 @@ let analyse_tds_fonction maintds (AstSyntax.Fonction(t, str, l_typstr, bloc)) = end end -(* analyser : AstSyntax.ast -> AstTds.ast *) -(* Paramètre : le programme à analyser *) -(* Vérifie la bonne utilisation des identifiants et tranforme le programme -en un programme de type AstTds.ast *) -(* Erreur si mauvaise utilisation des identifiants *) + +(* + analyser: + AstSyntax.ast -> AstTds.ast + Description: + Vérifie la bonne utilisation des identifiants et tranforme le programme en un programme de type AstTds.ast + Parameters: + - p : le programme à analyser + Returns: + L'AstTds correspondant au programme +*) let analyser (AstSyntax.Programme (typedefs,fonctions,prog)) = let tds = creerTDSMere () in let _ = List.map (analyse_tds_typedef tds) typedefs in diff --git a/src/passeTypeRat.ml b/src/passeTypeRat.ml index 26a7794..67e1319 100644 --- a/src/passeTypeRat.ml +++ b/src/passeTypeRat.ml @@ -12,6 +12,16 @@ struct type t2 = Ast.AstType.programme +(* + analyse_type_affectable: + AstTds.affectable -> affectable * typ + Description: + Vérifie le bon typage d'un affectable + Parameters: + - a : affectable a analyser + Returns: + Le nouvel affectable et son type +*) let rec analyse_type_affectable a = match a with | AstTds.Dref(a) -> @@ -20,6 +30,7 @@ let rec analyse_type_affectable a = | (na, Pointeur t) -> (AstType.Dref(na, t), t) | _ -> failwith "Internal Error" end + | AstTds.Ident(info) -> begin match info_ast_to_info info with @@ -27,6 +38,7 @@ let rec analyse_type_affectable a = | InfoConst _ -> (AstType.Ident(info), Int) | _ -> failwith "Internal Error" end + | AstTds.Attribut(aff, info) -> begin let (n_aff, _) = analyse_type_affectable aff in @@ -37,53 +49,63 @@ let rec analyse_type_affectable a = end -(* analyse_tds_expression : AstTds.expression -> (AstType.expression, type) *) -(* Paramètre tds : la table des symboles courante *) -(* Paramètre e : l'expression à analyser *) -(* Vérifie la bonne utilisation des identifiants et tranforme l'expression -en une expression de type AstType.expression *) -(* Erreur si mauvaise utilisation des identifiants *) +(* + analyse_type_expression: + AstTds.expression -> AstType.expression * typ + Description: + Vérifie la bonne utilisation des identifiants et tranforme l'expression en une expression de type AstType.expression + Parameters: + - e : l'expression à analyser + Returns: + Une nouvelle AstType.expression + Exceptions: + - TypesParametresInattendus + - TypeInattendu + - TypeBinaireInattendu +*) let rec analyse_type_expression e = match e with | AstTds.AppelFonction(info, l_expr) -> - begin let n_l_expr, l_type = List.split (List.map analyse_type_expression l_expr) in - match info_ast_to_info info with - | InfoFun(_, t, l_type_fun) -> - if (est_compatible_list l_type_fun l_type) then - (AstType.AppelFonction(info, n_l_expr), t) - else - raise (TypesParametresInattendus(l_type_fun, l_type)) - | _ -> failwith "Internal Error" - end + begin + match info_ast_to_info info with + | InfoFun(_, t, l_type_fun) -> + if (est_compatible_list l_type_fun l_type) then + (AstType.AppelFonction(info, n_l_expr), t) + else (* Les types mis en paramètre ne correpondent pas au types demandés *) + raise (TypesParametresInattendus(l_type_fun, l_type)) + | _ -> failwith "Internal Error" + end | AstTds.Unaire(u, expr) -> - begin - match (analyse_type_expression expr) with - | n_expr, Rat -> - begin - match u with - | AstSyntax.Numerateur -> (AstType.Unaire(Numerateur, n_expr), Int) - | AstSyntax.Denominateur -> (AstType.Unaire(Denominateur, n_expr), Int) - end - | _, t -> raise (TypeInattendu(t, Rat)) - end + begin + match (analyse_type_expression expr) with + | n_expr, Rat -> + begin + match u with + | AstSyntax.Numerateur -> (AstType.Unaire(Numerateur, n_expr), Int) + | AstSyntax.Denominateur -> (AstType.Unaire(Denominateur, n_expr), Int) + end + | _, t -> (* Il n'y a pas d'opérateur unaire autre que ceux sur les rat *) + raise (TypeInattendu(t, Rat)) + end | AstTds.Binaire(b, expr_1, expr_2) -> - begin let (n_expr_1, t1) = analyse_type_expression expr_1 in let (n_expr_2, t2) = analyse_type_expression expr_2 in - match (b, t1, t2) with - | Fraction, Int, Int -> (AstType.Binaire(Fraction, n_expr_1, n_expr_2), Rat) - | Plus, Int, Int -> (AstType.Binaire(PlusInt, n_expr_1, n_expr_2), Int) - | Mult, Int, Int -> (AstType.Binaire(MultInt, n_expr_1, n_expr_2), Int) - | Equ, Int ,Int -> (AstType.Binaire(EquInt, n_expr_1, n_expr_2), Bool) - | Inf, Int, Int -> (AstType.Binaire(Inf, n_expr_1, n_expr_2), Bool) - | Plus, Rat, Rat -> (AstType.Binaire(PlusRat, n_expr_1, n_expr_2), Rat) - | Mult, Rat, Rat -> (AstType.Binaire(MultRat, n_expr_1, n_expr_2), Rat) - | Equ, Bool ,Bool -> (AstType.Binaire(EquBool, n_expr_1, n_expr_2), Bool) - | _, _, _ -> raise (TypeBinaireInattendu(b, t1, t2)) - end + begin + match (b, t1, t2) with + | Fraction, Int, Int -> (AstType.Binaire(Fraction, n_expr_1, n_expr_2), Rat) + | Plus, Int, Int -> (AstType.Binaire(PlusInt, n_expr_1, n_expr_2), Int) + | Mult, Int, Int -> (AstType.Binaire(MultInt, n_expr_1, n_expr_2), Int) + | Equ, Int ,Int -> (AstType.Binaire(EquInt, n_expr_1, n_expr_2), Bool) + | Inf, Int, Int -> (AstType.Binaire(Inf, n_expr_1, n_expr_2), Bool) + | Plus, Rat, Rat -> (AstType.Binaire(PlusRat, n_expr_1, n_expr_2), Rat) + | Mult, Rat, Rat -> (AstType.Binaire(MultRat, n_expr_1, n_expr_2), Rat) + | Equ, Bool ,Bool -> (AstType.Binaire(EquBool, n_expr_1, n_expr_2), Bool) + | _, _, _ -> (* Opérations avec erreur de type *) + raise (TypeBinaireInattendu(b, t1, t2)) + end | AstTds.Booleen(b) -> (AstType.Booleen(b), Bool) @@ -111,12 +133,20 @@ let rec analyse_type_expression e = let n_l_expr, l_type = List.split (List.map analyse_type_expression l_expr) in (AstType.Tuple(n_l_expr), Struct(List.map (fun e -> (e, "")) l_type)) -(* analyse_tds_instruction : AstTds.instruction -> tds -> AstType.instruction *) -(* Paramètre tds : la table des symboles courante *) -(* Paramètre i : l'instruction à analyser *) -(* Vérifie la bonne utilisation des identifiants et tranforme l'instruction -en une instruction de type AstType.instruction *) -(* Erreur si mauvaise utilisation des identifiants *) + +(* + analyse_type_instruction: + typ option -> AstTds.instruction -> AstType.instruction + Description: + Vérifie la bonne utilisation des identifiants et tranforme l'instruction en une instruction de type AstType.instruction + Parameters: + - opt : permet de savoir si on est dans le main, ou dans une fonction + - i : l'instruction à analyser + Returns: + Une nouvelle AstType.instruction + Exceptions: + - TypeInattendu +*) let rec analyse_type_instruction opt i = match i with | AstTds.Declaration (t, info, e) -> @@ -137,6 +167,7 @@ let rec analyse_type_instruction opt i = | (na, Pointeur _) -> AstType.Affectation(na, ne) | _ -> failwith "Internal Error" end + | AstTds.Ident info -> begin match (info_ast_to_info info) with @@ -147,6 +178,7 @@ let rec analyse_type_instruction opt i = raise (TypeInattendu(nt, t)) | _ -> failwith "Internal Error" end + | AstTds.Attribut(aff2, info) -> begin match info_ast_to_info info with @@ -161,8 +193,8 @@ let rec analyse_type_instruction opt i = end | AstTds.Affichage e -> + let (ne, nt) = analyse_type_expression e in begin - let (ne, nt) = analyse_type_expression e in match nt with | Int -> AstType.AffichageInt(ne) | Rat -> AstType.AffichageRat(ne) @@ -173,62 +205,64 @@ let rec analyse_type_instruction opt i = end | AstTds.Conditionnelle (e, b1, b2) -> - begin - let (ne, nt) = analyse_type_expression e in - let nb1 = analyse_type_bloc opt b1 in - let nb2 = analyse_type_bloc opt b2 in - if (est_compatible Bool nt) then - AstType.Conditionnelle(ne, nb1, nb2) - else - raise (TypeInattendu(nt, Bool)) - end + let (ne, nt) = analyse_type_expression e in + let nb1 = analyse_type_bloc opt b1 in + let nb2 = analyse_type_bloc opt b2 in + if (est_compatible Bool nt) then + AstType.Conditionnelle(ne, nb1, nb2) + else + raise (TypeInattendu(nt, Bool)) - | AstTds.TantQue (e, b) -> - begin - let (ne, nt) = analyse_type_expression e in - if (est_compatible nt Bool) then - let nb = analyse_type_bloc opt b in - AstType.TantQue(ne, nb) - else - raise (TypeInattendu(nt, Bool)) - end + | AstTds.TantQue (e, b) -> + let (ne, nt) = analyse_type_expression e in + if (est_compatible nt Bool) then + let nb = analyse_type_bloc opt b in + AstType.TantQue(ne, nb) + else + raise (TypeInattendu(nt, Bool)) - | AstTds.Retour (e) -> + | AstTds.Retour (e) -> begin match opt with | Some(t) -> - let (ne, nt) = analyse_type_expression e in - if est_compatible t nt then + let (ne, nt) = analyse_type_expression e in + if est_compatible t nt then AstType.Retour(ne) - else + else raise (TypeInattendu(nt, t)) | None -> failwith "Internal Error" end - | AstTds.Empty -> AstType.Empty + | AstTds.Empty -> AstType.Empty -(* analyse_type_bloc : AstTds.bloc -> AstType.bloc *) -(* Paramètre tds : la table des symboles courante *) -(* Paramètre li : liste d'instructions à analyser *) -(* Vérifie la bonne utilisation des identifiants et tranforme le bloc -en un bloc de type AstType.bloc *) -(* Erreur si mauvaise utilisation des identifiants *) +(* + analyse_type_bloc: + typ option -> AstTds.bloc -> AstType.bloc + Description: + Vérifie la bonne utilisation des identifiants et tranforme le bloc en un bloc de type AstType.bloc + Parameters: + - opt : permet de savoir si on est dans le main, ou dans une fonction + - li : les instructions (bloc) à analyser + Returns: + Un nouvel AstType.bloc +*) and analyse_type_bloc opt li = let nli = List.map (analyse_type_instruction opt) li in nli - -(* analyse_type_fonction : AstTds.fonction -> AstType.fonction *) -(* Paramètre tds : la table des symboles courante *) -(* Paramètre : la fonction à analyser *) -(* Vérifie la bonne utilisation des identifiants et tranforme la fonction -en une fonction de type AstType.fonction *) -(* Erreur si mauvaise utilisation des identifiants *) (* - tds -> - AstTds.fonction[typ * string * (typ * string) list * bloc] -> - AstType.fonction[typ * Tds.info_ast * (typ * Tds.info_ast ) list * bloc] + analyse_type_fonction: + typ option -> AstTds.fonction -> AstType.fonction + Description: + Vérifie la bonne utilisation des identifiants et tranforme la fonction en une fonction de type AstTds.fonction + Parameters: + - opt : permet de savoir si on est dans le main, ou dans une fonction + - f : la fonction à analyser + Returns: + Une nouvelle AstTds.instruction + Exceptions: + - TypeInattendu *) let analyse_type_fonction opt (AstTds.Fonction(t, info, l_typinfo, bloc)) = match opt with @@ -245,12 +279,16 @@ let analyse_type_fonction opt (AstTds.Fonction(t, info, l_typinfo, bloc)) = raise (TypeInattendu(t, t_ret)) | None -> failwith "Internal Error" - -(* analyser : AstTds.ast -> AstType.ast *) -(* Paramètre : le programme à analyser *) -(* Vérifie la bonne utilisation des identifiants et tranforme le programme -en un programme de type AstType.ast *) -(* Erreur si mauvaise utilisation des identifiants *) +(* + analyser: + AstTds.ast -> AstType.ast + Description: + Vérifie la bonne utilisation des identifiants et tranforme le programme en un programme de type AstType.ast + Parameters: + - p : le programme à analyser + Returns: + L'AstType correspondant au programme +*) let analyser (AstTds.Programme(fonctions, prog)) = let nf = List.map (fun (AstTds.Fonction(t, info, l_typinfo, bloc)) -> analyse_type_fonction (Some t) (AstTds.Fonction(t, info, l_typinfo, bloc))) fonctions in