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.
## 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
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 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

View file

@ -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

View file

@ -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

View file

@ -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