jnfzefunzun

This commit is contained in:
Guillotin Damien 2022-01-11 15:52:40 +01:00
parent ae1324106a
commit c0df3ccd47
5 changed files with 400 additions and 178 deletions

View file

@ -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. 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 ## 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. 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. 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". \ 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`. \ 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é. \ 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 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

View file

@ -11,9 +11,21 @@ struct
type t1 = Ast.AstPlacement.programme type t1 = Ast.AstPlacement.programme
type t2 = string 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 = let rec getTailleAvant aff n =
match aff with match aff with
| Dref(aff2, _) -> getTailleAvant aff2 n | Dref(aff2, _) -> getTailleAvant aff2 n
| Ident(info) -> | Ident(info) ->
begin begin
match info_ast_to_info info with match info_ast_to_info info with
@ -28,6 +40,7 @@ let rec getTailleAvant aff n =
in tai in tai
| _ -> failwith "Internal Error" | _ -> failwith "Internal Error"
end end
| Attribut(aff2, info) -> | Attribut(aff2, info) ->
begin begin
match info_ast_to_info info with match info_ast_to_info info with
@ -38,15 +51,27 @@ let rec getTailleAvant aff n =
| _ -> failwith "Internal Error" | _ -> failwith "Internal Error"
end 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 = and getType aff =
match aff with match aff with
| Dref(aff2, _) -> getType aff2 | Dref(aff2, _) -> getType aff2
| Ident(info) -> | Ident(info) ->
begin begin
match info_ast_to_info info with match info_ast_to_info info with
| InfoVar(_, t, _, _) -> t | InfoVar(_, t, _, _) -> t
| _ -> failwith "Internal Error" | _ -> failwith "Internal Error"
end end
| Attribut(aff2, info) -> | Attribut(aff2, info) ->
begin begin
match info_ast_to_info info with match info_ast_to_info info with
@ -67,9 +92,21 @@ and getType aff =
| _ -> failwith "Internal Error" | _ -> failwith "Internal Error"
end 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 = and getTailleAttribut aff n =
match aff with match aff with
| Dref(aff2, _) -> getTailleAttribut aff2 n | Dref(aff2, _) -> getTailleAttribut aff2 n
| Ident(info) -> | Ident(info) ->
begin begin
match info_ast_to_info info with match info_ast_to_info info with
@ -83,17 +120,30 @@ and getTailleAttribut aff n =
) l_typstr 0 ) l_typstr 0
| _ -> failwith "Internal Error" | _ -> failwith "Internal Error"
end end
| Attribut(_, _) -> getTaille (getType aff) | 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 = and getBase aff =
match aff with match aff with
| Dref (a,_) -> getBase a | Dref (a,_) -> getBase a
| Ident(i) -> | Ident(i) ->
begin begin
match info_ast_to_info i with match info_ast_to_info i with
| InfoVar(_, _, base, _) -> base | InfoVar(_, _, base, _) -> base
| _ -> failwith "Internal Error" | _ -> failwith "Internal Error"
end end
| Attribut(a,i) -> | Attribut(a,i) ->
begin begin
match info_ast_to_info i with match info_ast_to_info i with
@ -105,24 +155,55 @@ and getBase aff =
| _ -> failwith "Internal Error" | _ -> failwith "Internal Error"
end 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 = and getReg aff =
match aff with match aff with
| Dref (a,_) -> getReg a | Dref (a,_) -> getReg a
| Ident(i) -> | Ident(i) ->
begin begin
match info_ast_to_info i with match info_ast_to_info i with
| InfoVar(_, _, _, reg) -> reg | InfoVar(_, _, _, reg) -> reg
| _ -> failwith "Internal Error" | _ -> failwith "Internal Error"
end end
| Attribut(a,_) -> getReg a | 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 = and extraction_info aff =
match aff with match aff with
| Dref(aff2, _) -> extraction_info aff2 | Dref(aff2, _) -> extraction_info aff2
| Ident(info) -> info | Ident(info) -> info
| Attribut(aff2, _) -> extraction_info aff2 | 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 = and analyse_code_affectable a =
match a with match a with
| Dref(aff, t) -> | Dref(aff, t) ->
@ -142,6 +223,16 @@ and analyse_code_affectable a =
let reg = getReg a in let reg = getReg a in
"LOAD (" ^ (string_of_int (getTaille (getType a))) ^ ") " ^ (string_of_int (base)) ^ "[" ^ reg ^ "]\n" "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 = and analyse_code_expression e =
match e with match e with
| AppelFonction(i, le) -> | AppelFonction(i, le) ->
@ -204,6 +295,19 @@ and analyse_code_expression e =
| Nothing -> "" | 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 = and analyse_code_instruction i taille_return taille_args taille_var =
match i with match i with
| Declaration(i, e) -> | Declaration(i, e) ->
@ -268,7 +372,6 @@ and analyse_code_instruction i taille_return taille_args taille_var =
"SUBR IOut\n" "SUBR IOut\n"
| AffichageStruct(e, t) -> | AffichageStruct(e, t) ->
let rec affichage base reg t0 = let rec affichage base reg t0 =
match t0 with match t0 with
| Struct(l_typstr) -> | Struct(l_typstr) ->
@ -284,6 +387,7 @@ and analyse_code_instruction i taille_return taille_args taille_var =
"LOADL ' '\n" ^ "LOADL ' '\n" ^
"SUBR COut\n" "SUBR COut\n"
,taille + (getTaille t)) ,taille + (getTaille t))
| Int -> ( | Int -> (
res ^ res ^
"LOAD (" ^ (string_of_int (getTaille t)) ^ ") " ^ (string_of_int taille) ^ "[" ^ reg ^ "]\n" ^ "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" ^ "LOADL ' '\n" ^
"SUBR COut\n" "SUBR COut\n"
,taille + (getTaille t)) ,taille + (getTaille t))
| Rat -> ( | Rat -> (
res ^ res ^
"LOAD (" ^ (string_of_int (getTaille t)) ^ ") " ^ (string_of_int taille) ^ "[" ^ reg ^ "]\n" ^ "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" ^ "LOADL ' '\n" ^
"SUBR COut\n" "SUBR COut\n"
,taille + (getTaille t)) ,taille + (getTaille t))
| Pointeur(_) -> ( | Pointeur(_) -> (
res ^ res ^
"LOADL '@'\n" ^ "LOADL '@'\n" ^
@ -307,6 +413,7 @@ and analyse_code_instruction i taille_return taille_args taille_var =
"LOADL ' '\n" ^ "LOADL ' '\n" ^
"SUBR COut\n" "SUBR COut\n"
,taille + (getTaille t)) ,taille + (getTaille t))
| Struct(_) -> ( | Struct(_) -> (
res ^ res ^
"LOADL '{'\n" ^ "LOADL '{'\n" ^
@ -317,7 +424,9 @@ and analyse_code_instruction i taille_return taille_args taille_var =
"LOADL ' '\n" ^ "LOADL ' '\n" ^
"SUBR COut\n" "SUBR COut\n"
,taille + (getTaille t)) ,taille + (getTaille t))
| _ -> failwith "Internal Error" | _ -> failwith "Internal Error"
) ("LOADL ' '\nSUBR COut\n", base) l_t in ) ("LOADL ' '\nSUBR COut\n", base) l_t in
res res
end end
@ -354,6 +463,7 @@ and analyse_code_instruction i taille_return taille_args taille_var =
begin begin
match a with match a with
| Dref(_, _) -> failwith "Internal Error" | Dref(_, _) -> failwith "Internal Error"
| Ident(i) -> | Ident(i) ->
begin begin
match info_ast_to_info i with 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 affichage base reg t
| _ -> failwith "Internal Error" | _ -> failwith "Internal Error"
end end
| Attribut(_, i) -> | Attribut(_, i) ->
match info_ast_to_info i with match info_ast_to_info i with
| InfoVar(_, t, _, _) -> | InfoVar(_, t, _, _) ->
@ -369,6 +480,7 @@ and analyse_code_instruction i taille_return taille_args taille_var =
affichage base reg t affichage base reg t
| _ -> failwith "Internal Error" | _ -> failwith "Internal Error"
end end
| AppelFonction(i, le) -> | AppelFonction(i, le) ->
begin begin
match info_ast_to_info i with 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" ^ "CALL (ST) " ^ nom ^ "\n" ^
(affichage base reg t) ^ (affichage base reg t) ^
"POP (0) " ^ (string_of_int (getTaille t)) ^ "\n" "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" | _ -> failwith "Internal Error"
end end
| _ -> failwith "Internal Error" | _ -> failwith "Internal Error"
@ -435,6 +531,18 @@ and analyse_code_instruction i taille_return taille_args taille_var =
| Empty -> "" | 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 = 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 let taille_var = string_of_int (List.fold_right (fun e res -> taille_variables_declarees e + res) bloc 0) in
List.fold_right ( List.fold_right (
@ -442,6 +550,16 @@ and analyse_code_bloc bloc taille_return taille_args =
) bloc "" ^ ) bloc "" ^
"POP (0) " ^ taille_var ^ "\n" "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)) = and analyse_code_fonction (AstPlacement.Fonction(info, _, bloc)) =
match info_ast_to_info info with match info_ast_to_info info with
| InfoFun(name, t, l_t) -> | InfoFun(name, t, l_t) ->
@ -453,6 +571,16 @@ and analyse_code_fonction (AstPlacement.Fonction(info, _, bloc)) =
| _ -> failwith "Internal Error" | _ -> 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 analyser (AstPlacement.Programme(fonctions, prog)) =
let code = getEntete () in let code = getEntete () in
let code = code ^ List.fold_right (fun e res -> (analyse_code_fonction e) ^ res) fonctions "" in let code = code ^ List.fold_right (fun e res -> (analyse_code_fonction e) ^ res) fonctions "" in

View file

@ -11,6 +11,18 @@ struct
type t2 = Ast.AstPlacement.programme 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 = let rec analyse_placement_instruction i base reg =
match i with match i with
| AstType.Declaration(info, _) -> | AstType.Declaration(info, _) ->
@ -34,6 +46,19 @@ let rec analyse_placement_instruction i base reg =
| _ -> 0 | _ -> 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 = and analyse_placement_bloc base reg bloc =
match bloc with match bloc with
| [] -> base | [] -> base
@ -41,6 +66,17 @@ and analyse_placement_bloc base reg bloc =
let taille = analyse_placement_instruction t base reg in let taille = analyse_placement_instruction t base reg in
analyse_placement_bloc (base + taille) reg q 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)) = and analyse_placement_fonction (AstType.Fonction(info, l_typinfo, bloc)) =
let _ = List.fold_right (fun x res_q -> let _ = List.fold_right (fun x res_q ->
begin begin
@ -51,9 +87,22 @@ and analyse_placement_fonction (AstType.Fonction(info, l_typinfo, bloc)) =
| _ -> failwith "Internal Error" | _ -> failwith "Internal Error"
end end
) l_typinfo 0 in ) 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 let _ = analyse_placement_bloc 3 "LB" bloc in
Fonction(info, l_typinfo, bloc) 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 analyser (AstType.Programme(fonctions, prog)) =
let n_fonctions = List.map analyse_placement_fonction fonctions in let n_fonctions = List.map analyse_placement_fonction fonctions in
let _ = analyse_placement_bloc 0 "SB" prog in let _ = analyse_placement_bloc 0 "SB" prog in

View file

@ -11,6 +11,7 @@ struct
type t1 = Ast.AstSyntax.programme type t1 = Ast.AstSyntax.programme
type t2 = Ast.AstTds.programme type t2 = Ast.AstTds.programme
(* (*
recherche_type: recherche_type:
tds -> typ -> typ tds -> typ -> typ
@ -21,10 +22,6 @@ struct
- t : le type que l'on cherche - t : le type que l'on cherche
Returns: Returns:
Le type d'un typedef Le type d'un typedef
Pre-conditions:
- True
Post-conditions:
- True
Exceptions: Exceptions:
- IdentifiantNonDeclare - IdentifiantNonDeclare
*) *)
@ -46,6 +43,7 @@ let rec recherche_type tds t =
Struct n_l_typstr Struct n_l_typstr
| _ -> t | _ -> t
(* (*
analyse_tds_affectable: analyse_tds_affectable:
tds -> AstSyntax.affectable -> bool -> AstTds.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 - modif : permet de savoir s'il sagit d'un affectable dans une expression ou dans une affectation
Returns: Returns:
Un nouvel AstTds.affectable Un nouvel AstTds.affectable
Pre-conditions:
- True
Post-conditions:
- True
Exceptions: Exceptions:
- IdentifiantNonDeclare - IdentifiantNonDeclare
- MauvaiseUtilisationIdentifiant - MauvaiseUtilisationIdentifiant
@ -102,10 +96,6 @@ let rec analyse_tds_affectable tds a modif =
- aff : Affectable dont on veut extraire l'info - aff : Affectable dont on veut extraire l'info
Returns: Returns:
L'info de l'affectable L'info de l'affectable
Pre-conditions:
- True
Post-conditions:
- True
*) *)
let rec extraction_info aff = let rec extraction_info aff =
match aff with 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 let t = List.fold_right (fun (t, n) res -> if str = n then t else res) l_att Undefined in
if t != Undefined then if t != Undefined then
AstTds.Attribut(n_aff, info_to_info_ast (InfoVar(str, t, 0, ""))) 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) 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) raise (MauvaiseUtilisationIdentifiant str)
end (** Ce ne peut etre qu'un InfoVar *) end (* Ce ne peut etre qu'un InfoVar *)
| _ -> raise (MauvaiseUtilisationIdentifiant str) | _ -> raise (MauvaiseUtilisationIdentifiant str)
(* (*
analyse_tds_affectable: analyse_tds_affectable:
tds -> AstSyntax.expression -> AstTds.expression tds -> AstSyntax.expression -> AstTds.expression
@ -141,10 +132,6 @@ let rec analyse_tds_affectable tds a modif =
- e : l'expression à analyser - e : l'expression à analyser
Returns: Returns:
Une nouvelle AstTds.expression Une nouvelle AstTds.expression
Pre-conditions:
- True
Post-conditions:
- True
Exceptions: Exceptions:
- IdentifiantNonDeclare - IdentifiantNonDeclare
- MauvaiseUtilisationIdentifiant - MauvaiseUtilisationIdentifiant
@ -216,10 +203,6 @@ let rec analyse_tds_expression tds e =
- td : le typedef à analyser - td : le typedef à analyser
Returns: Returns:
Une nouvelle AstTds.affectable Une nouvelle AstTds.affectable
Pre-conditions:
- True
Post-conditions:
- True
Exceptions: Exceptions:
- DoubleDeclaration - DoubleDeclaration
*) *)
@ -234,28 +217,21 @@ let analyse_tds_typedef tds (AstSyntax.TypeDef(n, t)) =
raise (DoubleDeclaration n) raise (DoubleDeclaration n)
end 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: analyse_tds_instruction:
tds -> AstSyntax.typedef -> AstTds.instruction tds -> AstSyntax.instruction -> AstTds.instruction
Description: 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: Parameters:
- tds : la table des symboles courante - tds : la table des symboles courante
- td : le typedef à analyser - i : l'instruction à analyser
Returns: Returns:
Une nouvelle AstTds.affectable Une nouvelle AstTds.instruction
Pre-conditions:
- True
Post-conditions:
- True
Exceptions: Exceptions:
- DoubleDeclaration - DoubleDeclaration
- IdentifiantNonDeclare
- MauvaiseUtilisationIdentifiant
*) *)
let rec analyse_tds_instruction tds i = let rec analyse_tds_instruction tds i =
match i with match i with
@ -366,39 +342,48 @@ let rec analyse_tds_instruction tds i =
(* Analyse du typedef *) (* Analyse du typedef *)
analyse_tds_typedef tds td 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 -> analyse_tds_bloc:
AstSyntax.fonction[typ * string * (typ * string) list * bloc] -> tds -> AstSyntax.bloc -> AstTds.bloc
AstTds.fonction[typ * Tds.info_ast * (typ * Tds.info_ast ) list * 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)) = let analyse_tds_fonction maintds (AstSyntax.Fonction(t, str, l_typstr, bloc)) =
begin begin
match chercherLocalement maintds str with 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 -> | None ->
begin begin
(* Copie de la tds globale dans la tds locale au bloc *) (* 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
end end
(* analyser : AstSyntax.ast -> AstTds.ast *)
(* Paramètre : le programme à analyser *) (*
(* Vérifie la bonne utilisation des identifiants et tranforme le programme analyser:
en un programme de type AstTds.ast *) AstSyntax.ast -> AstTds.ast
(* Erreur si mauvaise utilisation des identifiants *) 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 analyser (AstSyntax.Programme (typedefs,fonctions,prog)) =
let tds = creerTDSMere () in let tds = creerTDSMere () in
let _ = List.map (analyse_tds_typedef tds) typedefs in let _ = List.map (analyse_tds_typedef tds) typedefs in

View file

@ -12,6 +12,16 @@ struct
type t2 = Ast.AstType.programme 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 = let rec analyse_type_affectable a =
match a with match a with
| AstTds.Dref(a) -> | AstTds.Dref(a) ->
@ -20,6 +30,7 @@ let rec analyse_type_affectable a =
| (na, Pointeur t) -> (AstType.Dref(na, t), t) | (na, Pointeur t) -> (AstType.Dref(na, t), t)
| _ -> failwith "Internal Error" | _ -> failwith "Internal Error"
end end
| AstTds.Ident(info) -> | AstTds.Ident(info) ->
begin begin
match info_ast_to_info info with match info_ast_to_info info with
@ -27,6 +38,7 @@ let rec analyse_type_affectable a =
| InfoConst _ -> (AstType.Ident(info), Int) | InfoConst _ -> (AstType.Ident(info), Int)
| _ -> failwith "Internal Error" | _ -> failwith "Internal Error"
end end
| AstTds.Attribut(aff, info) -> | AstTds.Attribut(aff, info) ->
begin begin
let (n_aff, _) = analyse_type_affectable aff in let (n_aff, _) = analyse_type_affectable aff in
@ -37,53 +49,63 @@ let rec analyse_type_affectable a =
end end
(* analyse_tds_expression : AstTds.expression -> (AstType.expression, type) *) (*
(* Paramètre tds : la table des symboles courante *) analyse_type_expression:
(* Paramètre e : l'expression à analyser *) AstTds.expression -> AstType.expression * typ
(* Vérifie la bonne utilisation des identifiants et tranforme l'expression Description:
en une expression de type AstType.expression *) Vérifie la bonne utilisation des identifiants et tranforme l'expression en une expression de type AstType.expression
(* Erreur si mauvaise utilisation des identifiants *) Parameters:
- e : l'expression à analyser
Returns:
Une nouvelle AstType.expression
Exceptions:
- TypesParametresInattendus
- TypeInattendu
- TypeBinaireInattendu
*)
let rec analyse_type_expression e = let rec analyse_type_expression e =
match e with match e with
| AstTds.AppelFonction(info, l_expr) -> | AstTds.AppelFonction(info, l_expr) ->
begin
let n_l_expr, l_type = List.split (List.map analyse_type_expression l_expr) in let n_l_expr, l_type = List.split (List.map analyse_type_expression l_expr) in
match info_ast_to_info info with begin
| InfoFun(_, t, l_type_fun) -> match info_ast_to_info info with
if (est_compatible_list l_type_fun l_type) then | InfoFun(_, t, l_type_fun) ->
(AstType.AppelFonction(info, n_l_expr), t) if (est_compatible_list l_type_fun l_type) then
else (AstType.AppelFonction(info, n_l_expr), t)
raise (TypesParametresInattendus(l_type_fun, l_type)) else (* Les types mis en paramètre ne correpondent pas au types demandés *)
| _ -> failwith "Internal Error" raise (TypesParametresInattendus(l_type_fun, l_type))
end | _ -> failwith "Internal Error"
end
| AstTds.Unaire(u, expr) -> | AstTds.Unaire(u, expr) ->
begin begin
match (analyse_type_expression expr) with match (analyse_type_expression expr) with
| n_expr, Rat -> | n_expr, Rat ->
begin begin
match u with match u with
| AstSyntax.Numerateur -> (AstType.Unaire(Numerateur, n_expr), Int) | AstSyntax.Numerateur -> (AstType.Unaire(Numerateur, n_expr), Int)
| AstSyntax.Denominateur -> (AstType.Unaire(Denominateur, n_expr), Int) | AstSyntax.Denominateur -> (AstType.Unaire(Denominateur, n_expr), Int)
end end
| _, t -> raise (TypeInattendu(t, Rat)) | _, t -> (* Il n'y a pas d'opérateur unaire autre que ceux sur les rat *)
end raise (TypeInattendu(t, Rat))
end
| AstTds.Binaire(b, expr_1, expr_2) -> | AstTds.Binaire(b, expr_1, expr_2) ->
begin
let (n_expr_1, t1) = analyse_type_expression expr_1 in let (n_expr_1, t1) = analyse_type_expression expr_1 in
let (n_expr_2, t2) = analyse_type_expression expr_2 in let (n_expr_2, t2) = analyse_type_expression expr_2 in
match (b, t1, t2) with begin
| Fraction, Int, Int -> (AstType.Binaire(Fraction, n_expr_1, n_expr_2), Rat) match (b, t1, t2) with
| Plus, Int, Int -> (AstType.Binaire(PlusInt, n_expr_1, n_expr_2), Int) | Fraction, Int, Int -> (AstType.Binaire(Fraction, n_expr_1, n_expr_2), Rat)
| Mult, Int, Int -> (AstType.Binaire(MultInt, n_expr_1, n_expr_2), Int) | Plus, Int, Int -> (AstType.Binaire(PlusInt, n_expr_1, n_expr_2), Int)
| Equ, Int ,Int -> (AstType.Binaire(EquInt, n_expr_1, n_expr_2), Bool) | Mult, Int, Int -> (AstType.Binaire(MultInt, n_expr_1, n_expr_2), Int)
| Inf, Int, Int -> (AstType.Binaire(Inf, n_expr_1, n_expr_2), Bool) | Equ, Int ,Int -> (AstType.Binaire(EquInt, n_expr_1, n_expr_2), Bool)
| Plus, Rat, Rat -> (AstType.Binaire(PlusRat, n_expr_1, n_expr_2), Rat) | Inf, Int, Int -> (AstType.Binaire(Inf, n_expr_1, n_expr_2), Bool)
| Mult, Rat, Rat -> (AstType.Binaire(MultRat, n_expr_1, n_expr_2), Rat) | Plus, Rat, Rat -> (AstType.Binaire(PlusRat, n_expr_1, n_expr_2), Rat)
| Equ, Bool ,Bool -> (AstType.Binaire(EquBool, n_expr_1, n_expr_2), Bool) | Mult, Rat, Rat -> (AstType.Binaire(MultRat, n_expr_1, n_expr_2), Rat)
| _, _, _ -> raise (TypeBinaireInattendu(b, t1, t2)) | Equ, Bool ,Bool -> (AstType.Binaire(EquBool, n_expr_1, n_expr_2), Bool)
end | _, _, _ -> (* Opérations avec erreur de type *)
raise (TypeBinaireInattendu(b, t1, t2))
end
| AstTds.Booleen(b) -> (AstType.Booleen(b), Bool) | 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 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)) (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 *) analyse_type_instruction:
(* Vérifie la bonne utilisation des identifiants et tranforme l'instruction typ option -> AstTds.instruction -> AstType.instruction
en une instruction de type AstType.instruction *) Description:
(* Erreur si mauvaise utilisation des identifiants *) 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 = let rec analyse_type_instruction opt i =
match i with match i with
| AstTds.Declaration (t, info, e) -> | AstTds.Declaration (t, info, e) ->
@ -137,6 +167,7 @@ let rec analyse_type_instruction opt i =
| (na, Pointeur _) -> AstType.Affectation(na, ne) | (na, Pointeur _) -> AstType.Affectation(na, ne)
| _ -> failwith "Internal Error" | _ -> failwith "Internal Error"
end end
| AstTds.Ident info -> | AstTds.Ident info ->
begin begin
match (info_ast_to_info info) with match (info_ast_to_info info) with
@ -147,6 +178,7 @@ let rec analyse_type_instruction opt i =
raise (TypeInattendu(nt, t)) raise (TypeInattendu(nt, t))
| _ -> failwith "Internal Error" | _ -> failwith "Internal Error"
end end
| AstTds.Attribut(aff2, info) -> | AstTds.Attribut(aff2, info) ->
begin begin
match info_ast_to_info info with match info_ast_to_info info with
@ -161,8 +193,8 @@ let rec analyse_type_instruction opt i =
end end
| AstTds.Affichage e -> | AstTds.Affichage e ->
let (ne, nt) = analyse_type_expression e in
begin begin
let (ne, nt) = analyse_type_expression e in
match nt with match nt with
| Int -> AstType.AffichageInt(ne) | Int -> AstType.AffichageInt(ne)
| Rat -> AstType.AffichageRat(ne) | Rat -> AstType.AffichageRat(ne)
@ -173,62 +205,64 @@ let rec analyse_type_instruction opt i =
end end
| AstTds.Conditionnelle (e, b1, b2) -> | AstTds.Conditionnelle (e, b1, b2) ->
begin let (ne, nt) = analyse_type_expression e in
let (ne, nt) = analyse_type_expression e in let nb1 = analyse_type_bloc opt b1 in
let nb1 = analyse_type_bloc opt b1 in let nb2 = analyse_type_bloc opt b2 in
let nb2 = analyse_type_bloc opt b2 in if (est_compatible Bool nt) then
if (est_compatible Bool nt) then AstType.Conditionnelle(ne, nb1, nb2)
AstType.Conditionnelle(ne, nb1, nb2) else
else raise (TypeInattendu(nt, Bool))
raise (TypeInattendu(nt, Bool))
end
| AstTds.TantQue (e, b) -> | AstTds.TantQue (e, b) ->
begin let (ne, nt) = analyse_type_expression e in
let (ne, nt) = analyse_type_expression e in if (est_compatible nt Bool) then
if (est_compatible nt Bool) then let nb = analyse_type_bloc opt b in
let nb = analyse_type_bloc opt b in AstType.TantQue(ne, nb)
AstType.TantQue(ne, nb) else
else raise (TypeInattendu(nt, Bool))
raise (TypeInattendu(nt, Bool))
end
| AstTds.Retour (e) -> | AstTds.Retour (e) ->
begin begin
match opt with match opt with
| Some(t) -> | Some(t) ->
let (ne, nt) = analyse_type_expression e in let (ne, nt) = analyse_type_expression e in
if est_compatible t nt then if est_compatible t nt then
AstType.Retour(ne) AstType.Retour(ne)
else else
raise (TypeInattendu(nt, t)) raise (TypeInattendu(nt, t))
| None -> failwith "Internal Error" | None -> failwith "Internal Error"
end end
| AstTds.Empty -> AstType.Empty | AstTds.Empty -> AstType.Empty
(* analyse_type_bloc : AstTds.bloc -> AstType.bloc *) (*
(* Paramètre tds : la table des symboles courante *) analyse_type_bloc:
(* Paramètre li : liste d'instructions à analyser *) typ option -> AstTds.bloc -> AstType.bloc
(* Vérifie la bonne utilisation des identifiants et tranforme le bloc Description:
en un bloc de type AstType.bloc *) Vérifie la bonne utilisation des identifiants et tranforme le bloc en un bloc de type AstType.bloc
(* Erreur si mauvaise utilisation des identifiants *) 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 = and analyse_type_bloc opt li =
let nli = List.map (analyse_type_instruction opt) li in let nli = List.map (analyse_type_instruction opt) li in
nli 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 -> analyse_type_fonction:
AstTds.fonction[typ * string * (typ * string) list * bloc] -> typ option -> AstTds.fonction -> AstType.fonction
AstType.fonction[typ * Tds.info_ast * (typ * Tds.info_ast ) list * bloc] 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)) = let analyse_type_fonction opt (AstTds.Fonction(t, info, l_typinfo, bloc)) =
match opt with match opt with
@ -245,12 +279,16 @@ let analyse_type_fonction opt (AstTds.Fonction(t, info, l_typinfo, bloc)) =
raise (TypeInattendu(t, t_ret)) raise (TypeInattendu(t, t_ret))
| None -> failwith "Internal Error" | None -> failwith "Internal Error"
(*
(* analyser : AstTds.ast -> AstType.ast *) analyser:
(* Paramètre : le programme à analyser *) AstTds.ast -> AstType.ast
(* Vérifie la bonne utilisation des identifiants et tranforme le programme Description:
en un programme de type AstType.ast *) Vérifie la bonne utilisation des identifiants et tranforme le programme en un programme de type AstType.ast
(* Erreur si mauvaise utilisation des identifiants *) Parameters:
- p : le programme à analyser
Returns:
L'AstType correspondant au programme
*)
let analyser (AstTds.Programme(fonctions, prog)) = let analyser (AstTds.Programme(fonctions, prog)) =
let nf = List.map (fun (AstTds.Fonction(t, info, l_typinfo, bloc)) -> 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 analyse_type_fonction (Some t) (AstTds.Fonction(t, info, l_typinfo, bloc))) fonctions in