-
Notifications
You must be signed in to change notification settings - Fork 0
/
passe.ml
109 lines (88 loc) · 3.65 KB
/
passe.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
(* 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 AstSyntax.programme -> AstTds.programme *)
(* Ne fait rien *)
(* Nécessaire aux compilateurs intermédiaires (non complets) *)
module PasseTdsNop : Passe with type t1 = Ast.AstSyntax.programme and type t2 = Ast.AstTds.programme =
struct
type t1 = Ast.AstSyntax.programme
type t2 = Ast.AstTds.programme
let analyser _ = Ast.AstTds.Programme([],[])
end
(* Passe AstTds.programme -> AstType.programme *)
(* Ne fait rien *)
(* Nécessaire aux compilateurs intermédiaires (non complets) *)
module PasseTypeNop : Passe with type t1 = Ast.AstTds.programme and type t2 = Ast.AstType.programme =
struct
type t1 = Ast.AstTds.programme
type t2 = Ast.AstType.programme
let analyser _ = Ast.AstType.Programme([],[])
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 = Ast.AstPlacement.programme =
struct
type t1 = Ast.AstType.programme
type t2 = Ast.AstPlacement.programme
let analyser _ = Ast.AstPlacement.Programme([],([],0))
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
(* 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 VerifPlacement =
struct
open Mtds
(* Renvoie l'adresse d'une variable dans le cas d'une déclaration *)
let rec analyser_instruction i =
match i with
| Ast.AstPlacement.Declaration (info,_) ->
begin
match info with
| InfoVar (n,_,d,r) -> [(fst n,(!d,!r))]
| _ -> []
end
| Ast.AstPlacement.Conditionnelle(_,(bt,_),(be,_)) ->
(List.flatten (List.map (analyser_instruction) (List.map fst bt)))
@ (List.flatten (List.map (analyser_instruction) (List.map fst be)))
| Ast.AstPlacement.TantQue (_,(b,_)) ->
(List.flatten (List.map (analyser_instruction) (List.map fst b)))
| _ -> []
let analyser_param info =
match info with
| InfoVar (n,_,d,r) -> [(fst 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 with
| InfoFun([n,_,_]) -> [(fst n,
(List.flatten (List.map analyser_param lp))
@ (List.flatten (List.map (analyser_instruction) (List.map fst 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) (List.map fst prog)))
::(List.flatten (List.map (analyser_fonction) fonctions))
end