1 (***********************************************************************)
5 (* Damien Doligez, projet Cristal, INRIA Rocquencourt *)
7 (* Copyright 2004 Institut National de Recherche en Informatique et *)
8 (* en Automatique. All rights reserved. This file is distributed *)
9 (* under the terms of the Q Public License version 1.0. *)
11 (***********************************************************************)
17 let silent v
= String.length v
> 0 && v
.[0] = '_'
;;
19 let add_vars tbl
(vll1
, vll2
) =
20 let add_var (v
, _loc
, used
) = Hashtbl.add tbl v used
in
21 List.iter
add_var vll1
;
22 List.iter
add_var vll2
;
25 let rm_vars tbl
(vll1
, vll2
) =
26 let rm_var (v
, _
, _
) = Hashtbl.remove tbl v
in
27 List.iter
rm_var vll1
;
28 List.iter
rm_var vll2
;
31 let w_suspicious x
= Warnings.Unused_var x
;;
32 let w_strict x
= Warnings.Unused_var_strict x
;;
34 let check_rm_vars ppf tbl
(vlul_pat
, vlul_as
) =
35 let check_rm_var kind
(v
, loc
, used
) =
36 if not
!used
&& not
(silent v
)
37 then Location.print_warning loc ppf
(kind v
);
40 List.iter
(check_rm_var w_strict) vlul_pat
;
41 List.iter
(check_rm_var w_suspicious) vlul_as
;
44 let check_rm_let ppf tbl vlulpl
=
45 let check_rm_one flag
(v
, loc
, used
) =
47 flag
&& (silent v
|| not
!used
)
49 let warn_var w_kind
(v
, loc
, used
) =
50 if not
(silent v
) && not
!used
51 then Location.print_warning loc ppf
(w_kind v
)
53 let check_rm_pat (def
, def_as
) =
54 let def_unused = List.fold_left
check_rm_one true def
in
55 let all_unused = List.fold_left
check_rm_one def_unused def_as
in
56 List.iter
(warn_var (if all_unused then w_suspicious else w_strict)) def
;
57 List.iter
(warn_var w_suspicious) def_as
;
59 List.iter
check_rm_pat vlulpl
;
62 let rec get_vars ((vacc
, asacc
) as acc
) p
=
63 match p
.ppat_desc
with
65 | Ppat_var v
-> ((v
, p
.ppat_loc
, ref false) :: vacc
, asacc
)
66 | Ppat_alias
(pp
, v
) ->
67 get_vars (vacc
, ((v
, p
.ppat_loc
, ref false) :: asacc
)) pp
68 | Ppat_constant _
-> acc
69 | Ppat_tuple pl
-> List.fold_left
get_vars acc pl
70 | Ppat_construct
(_
, po
, _
) -> get_vars_option acc po
71 | Ppat_variant
(_
, po
) -> get_vars_option acc po
73 List.fold_left
(fun a
(_
, p
) -> get_vars a p
) acc ipl
74 | Ppat_array pl
-> List.fold_left
get_vars acc pl
75 | Ppat_or
(p1
, _p2
) -> get_vars acc p1
76 | Ppat_constraint
(pp
, _
) -> get_vars acc pp
79 and get_vars_option acc po
=
81 | Some p
-> get_vars acc p
85 let get_pel_vars pel
=
86 List.map
(fun (p
, _
) -> get_vars ([], []) p
) pel
89 let rec structure ppf tbl l
=
90 List.iter
(structure_item ppf tbl
) l
92 and structure_item ppf tbl s
=
93 match s
.pstr_desc
with
94 | Pstr_eval e
-> expression ppf tbl e
;
95 | Pstr_value
(recflag
, pel
) -> let_pel ppf tbl recflag pel None
;
96 | Pstr_primitive _
-> ()
98 | Pstr_exception _
-> ()
99 | Pstr_exn_rebind _
-> ()
100 | Pstr_module
(_
, me
) -> module_expr ppf tbl me
;
101 | Pstr_recmodule stml
->
102 List.iter
(fun (_
, _
, me
) -> module_expr ppf tbl me
) stml
;
103 | Pstr_modtype _
-> ()
105 | Pstr_class cdl
-> List.iter
(class_declaration ppf tbl
) cdl
;
106 | Pstr_class_type _
-> ()
107 | Pstr_include _
-> ()
109 and expression ppf tbl e
=
110 match e
.pexp_desc
with
111 | Pexp_ident
(Longident.Lident id
) ->
112 begin try (Hashtbl.find tbl id
) := true;
116 | Pexp_constant _
-> ()
117 | Pexp_let
(recflag
, pel
, e
) ->
118 let_pel ppf tbl recflag pel
(Some
(fun ppf tbl
-> expression ppf tbl e
));
119 | Pexp_function
(_
, eo
, pel
) ->
120 expression_option ppf tbl eo
;
121 match_pel ppf tbl pel
;
122 | Pexp_apply
(e
, lel
) ->
123 expression ppf tbl e
;
124 List.iter
(fun (_
, e
) -> expression ppf tbl e
) lel
;
125 | Pexp_match
(e
, pel
) ->
126 expression ppf tbl e
;
127 match_pel ppf tbl pel
;
128 | Pexp_try
(e
, pel
) ->
129 expression ppf tbl e
;
130 match_pel ppf tbl pel
;
131 | Pexp_tuple el
-> List.iter
(expression ppf tbl
) el
;
132 | Pexp_construct
(_
, eo
, _
) -> expression_option ppf tbl eo
;
133 | Pexp_variant
(_
, eo
) -> expression_option ppf tbl eo
;
134 | Pexp_record
(iel
, eo
) ->
135 List.iter
(fun (_
, e
) -> expression ppf tbl e
) iel
;
136 expression_option ppf tbl eo
;
137 | Pexp_field
(e
, _
) -> expression ppf tbl e
;
138 | Pexp_setfield
(e1
, _
, e2
) ->
139 expression ppf tbl e1
;
140 expression ppf tbl e2
;
141 | Pexp_array el
-> List.iter
(expression ppf tbl
) el
;
142 | Pexp_ifthenelse
(e1
, e2
, eo
) ->
143 expression ppf tbl e1
;
144 expression ppf tbl e2
;
145 expression_option ppf tbl eo
;
146 | Pexp_sequence
(e1
, e2
) ->
147 expression ppf tbl e1
;
148 expression ppf tbl e2
;
149 | Pexp_while
(e1
, e2
) ->
150 expression ppf tbl e1
;
151 expression ppf tbl e2
;
152 | Pexp_for
(id
, e1
, e2
, _
, e3
) ->
153 expression ppf tbl e1
;
154 expression ppf tbl e2
;
155 let defined = ([ (id
, e
.pexp_loc
, ref true) ], []) in
156 add_vars tbl
defined;
157 expression ppf tbl e3
;
158 check_rm_vars ppf tbl
defined;
159 | Pexp_constraint
(e
, _
, _
) -> expression ppf tbl e
;
160 | Pexp_when
(e1
, e2
) ->
161 expression ppf tbl e1
;
162 expression ppf tbl e2
;
163 | Pexp_send
(e
, _
) -> expression ppf tbl e
;
165 | Pexp_setinstvar
(_
, e
) -> expression ppf tbl e
;
166 | Pexp_override sel
-> List.iter
(fun (_
, e
) -> expression ppf tbl e
) sel
;
167 | Pexp_letmodule
(_
, me
, e
) ->
168 module_expr ppf tbl me
;
169 expression ppf tbl e
;
170 | Pexp_assert e
-> expression ppf tbl e
;
171 | Pexp_assertfalse
-> ()
172 | Pexp_lazy e
-> expression ppf tbl e
;
173 | Pexp_poly
(e
, _
) -> expression ppf tbl e
;
174 | Pexp_object cs
-> class_structure ppf tbl cs
;
176 and expression_option ppf tbl eo
=
178 | Some e
-> expression ppf tbl e
;
181 and let_pel ppf tbl recflag pel body
=
183 | Asttypes.Recursive
->
184 let defined = get_pel_vars pel
in
185 List.iter
(add_vars tbl
) defined;
186 List.iter
(fun (_
, e
) -> expression ppf tbl e
) pel
;
187 begin match body
with
189 List.iter
(rm_vars tbl
) defined;
192 check_rm_let ppf tbl
defined;
195 List.iter
(fun (_
, e
) -> expression
ppf tbl e
) pel
;
196 begin match body
with
199 let defined = get_pel_vars pel
in
200 List.iter
(add_vars tbl
) defined;
202 check_rm_let ppf tbl
defined;
205 and match_pel
ppf tbl pel
=
206 List.iter
(match_pe
ppf tbl
) pel
208 and match_pe
ppf tbl
(p
, e
) =
209 let defined = get_vars ([], []) p
in
210 add_vars tbl
defined;
211 expression
ppf tbl e
;
212 check_rm_vars ppf tbl
defined;
214 and module_expr
ppf tbl me
=
215 match me
.pmod_desc
with
217 | Pmod_structure s
-> structure ppf tbl s
218 | Pmod_functor
(_
, _
, me
) -> module_expr
ppf tbl me
219 | Pmod_apply
(me1
, me2
) ->
220 module_expr
ppf tbl me1
;
221 module_expr
ppf tbl me2
;
222 | Pmod_constraint
(me
, _
) -> module_expr
ppf tbl me
224 and class_declaration
ppf tbl cd
= class_expr
ppf tbl cd
.pci_expr
226 and class_expr
ppf tbl ce
=
227 match ce
.pcl_desc
with
229 | Pcl_structure cs
-> class_structure
ppf tbl cs
;
230 | Pcl_fun
(_
, _
, _
, ce
) -> class_expr
ppf tbl ce
;
231 | Pcl_apply
(ce
, lel
) ->
232 class_expr
ppf tbl ce
;
233 List.iter
(fun (_
, e
) -> expression
ppf tbl e
) lel
;
234 | Pcl_let
(recflag
, pel
, ce
) ->
235 let_pel
ppf tbl recflag pel
(Some
(fun ppf tbl
-> class_expr
ppf tbl ce
));
236 | Pcl_constraint
(ce
, _
) -> class_expr
ppf tbl ce
;
238 and class_structure
ppf tbl
(p
, cfl
) =
239 let defined = get_vars ([], []) p
in
240 add_vars tbl
defined;
241 List.iter
(class_field
ppf tbl
) cfl
;
242 check_rm_vars ppf tbl
defined;
244 and class_field
ppf tbl cf
=
246 | Pcf_inher
(ce
, _
) -> class_expr
ppf tbl ce
;
247 | Pcf_val
(_
, _
, e
, _
) -> expression
ppf tbl e
;
248 | Pcf_virt _
| Pcf_valvirt _
-> ()
249 | Pcf_meth
(_
, _
, e
, _
) -> expression
ppf tbl e
;
251 | Pcf_let
(recflag
, pel
, _
) -> let_pel
ppf tbl recflag pel None
;
252 | Pcf_init e
-> expression
ppf tbl e
;
256 if Warnings.is_active
(w_suspicious "") || Warnings.is_active
(w_strict "")
258 let tbl = Hashtbl.create
97 in
259 structure ppf tbl ast
;