projet-traduction-langage/passe.ml
2021-11-24 14:13:45 +01:00

131 lines
4 KiB
OCaml

(* Interface définissant une passe *)
module type Passe =
sig
(* type des AST en entrée de la passe *)
type t1
(* type des AST en sortie de la passe *)
type t2
(* fonction d'analyse qui tranforme un AST de type t1
en un AST de type t2 en réalisant des vérifications *)
val analyser : t1 -> t2
end
(* Passe unit -> unit *)
(* Ne fait rien *)
(* Nécessaire aux compilateurs intermédiaires (non complets) *)
module PasseNop : Passe with type t1 = unit and type t2 = unit =
struct
type t1 = unit
type t2 = unit
let analyser _ = ()
end
(* Passe AstSyntax.programme -> unit *)
(* Ne fait rien *)
(* Nécessaire aux compilateurs intermédiaires (non complets) *)
module PasseTdsNop : Passe with type t1 = Ast.AstSyntax.programme and type t2 = unit =
struct
type t1 = Ast.AstSyntax.programme
type t2 = unit
let analyser _ = ()
end
(* Passe unit -> string *)
(* Ne fait rien *)
(* Nécessaire aux compilateurs intermédiaires (non complets) *)
module PasseCodeNopNop : Passe with type t1 = unit and type t2 = string =
struct
type t1 = unit
type t2 = string
let analyser _ = ""
end
(* Passe AstTds.programme -> unit *)
(* Ne fait rien *)
(* Nécessaire aux compilateurs intermédiaires (non complets) *)
module PasseTypeNop : Passe with type t1 = Ast.AstTds.programme and type t2 = unit =
struct
type t1 = Ast.AstTds.programme
type t2 = unit
let analyser _ = ()
end
(* Passe AstType.programme -> unit *)
(* Ne fait rien *)
(* Nécessaire aux compilateurs intermédiaires (non complets) *)
module PassePlacementNop : Passe with type t1 = Ast.AstType.programme and type t2 = unit =
struct
type t1 = Ast.AstType.programme
type t2 = unit
let analyser _ = ()
end
(* Passe AstPlacement.programme -> string *)
(* Affiche les adresses des variables *)
(* Pour tester les paramètres des fonctions, il est nécessaire de les mettre en retour *)
module PasseVerifPlacement : Passe with type t1 = Ast.AstPlacement.programme and type t2 = (string *(string*(int*string)) list) list =
struct
open Tds
type t1 = Ast.AstPlacement.programme
type t2 = (string *(string*(int*string)) list) list
(* Renvoie l'adresse d'une variable dans le cas d'une déclaration *)
let rec analyser_instruction i =
match i with
| Ast.AstType.Declaration (info,_) ->
begin
match Tds.info_ast_to_info info with
| InfoVar (n,_,d,r) -> [(n,(d,r))]
| _ -> []
end
| Ast.AstType.Conditionnelle(_,bt,be) -> (List.flatten (List.map (analyser_instruction) bt))@(List.flatten (List.map (analyser_instruction) be))
| Ast.AstType.TantQue (_,b) -> (List.flatten (List.map (analyser_instruction) b))
| _ -> [] ;;
let analyser_param info =
match Tds.info_ast_to_info info with
| InfoVar (n,_,d,r) -> [(n,(d,r))]
| _ -> []
(* Renvoie la suite des adresses des variables déclarées dans la fonction *)
(* Ainsi qu'une adresse d'identifiant si le retour est un identifiant *)
let analyser_fonction (Ast.AstPlacement.Fonction(info,lp,li)) =
(*La liste des paramètres n'est plus présente, pour tester le placement des paramètres, on utilisera une astuce :
il faudra écrire un programme qui renvoie le paramètre *)
match info_ast_to_info info with
| InfoFun(n,_,_) -> [(n,(List.flatten (List.map analyser_param lp))@(List.flatten (List.map (analyser_instruction) li)))]
| _ -> failwith "Internal error"
(* Renvoie la suite des adresses des variables déclarées dans les fonctions et dans le programme principal *)
let analyser (Ast.AstPlacement.Programme (fonctions, prog)) =
("main", List.flatten (List.map (analyser_instruction) prog))::(List.flatten (List.map (analyser_fonction) fonctions))
end
(* Passe AstPlacement.programme -> string *)
(* Ne fait rien *)
(* Nécessaire aux compilateurs intermédiaires (non complets) *)
module PasseCodeNop : Passe with type t1 = Ast.AstPlacement.programme and type t2 = string =
struct
type t1 = Ast.AstPlacement.programme
type t2 = string
let analyser _ = ""
end