Commit | Line | Data |
---|---|---|
0708f913 | 1 | (* Yoann Padioleau |
ae4735db C |
2 | * |
3 | * Copyright (C) 2010, University of Copenhagen DIKU and INRIA. | |
0708f913 C |
4 | * Copyright (C) 2008, 2009 University of Urbana Champaign |
5 | * | |
6 | * This program is free software; you can redistribute it and/or | |
7 | * modify it under the terms of the GNU General Public License (GPL) | |
8 | * version 2 as published by the Free Software Foundation. | |
ae4735db | 9 | * |
0708f913 C |
10 | * This program is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | * file license.txt for more details. | |
14 | *) | |
15 | ||
ae4735db | 16 | open Common |
485bce71 C |
17 | |
18 | (* if do .mli: | |
19 | val print_parsing_stat_list: parsing_stat list -> unit | |
20 | *) | |
21 | ||
22 | (*****************************************************************************) | |
23 | (* Stat *) | |
24 | (*****************************************************************************) | |
25 | type parsing_stat = { | |
26 | filename: filename; | |
27 | mutable have_timeout: bool; | |
28 | ||
ae4735db | 29 | mutable correct: int; |
485bce71 C |
30 | mutable bad: int; |
31 | ||
32 | mutable commentized: int; (* by our cpp commentizer *) | |
33 | ||
34 | (* if want to know exactly what was passed through, uncomment: | |
ae4735db | 35 | * |
485bce71 | 36 | * mutable passing_through_lines: int; |
ae4735db | 37 | * |
485bce71 C |
38 | * it differs from bad by starting from the error to |
39 | * the synchro point instead of starting from start of | |
40 | * function to end of function. | |
41 | *) | |
42 | ||
ae4735db | 43 | mutable problematic_lines: |
91eba41f C |
44 | (string list (* ident in error line *) * int (* line_error *)) list; |
45 | ||
ae4735db | 46 | } |
485bce71 | 47 | |
ae4735db | 48 | let default_stat file = { |
485bce71 C |
49 | filename = file; |
50 | have_timeout = false; | |
51 | correct = 0; bad = 0; | |
52 | commentized = 0; | |
91eba41f | 53 | problematic_lines = []; |
485bce71 C |
54 | } |
55 | ||
ae4735db C |
56 | (* todo: stat per dir ? give in terms of func_or_decl numbers: |
57 | * nbfunc_or_decl pbs / nbfunc_or_decl total ?/ | |
485bce71 | 58 | * |
ae4735db C |
59 | * note: cela dit si y'a des fichiers avec des #ifdef dont on connait pas les |
60 | * valeurs alors on parsera correctement tout le fichier et pourtant y'aura | |
61 | * aucune def et donc aucune couverture en fait. | |
62 | * ==> TODO evaluer les parties non parsé ? | |
485bce71 C |
63 | *) |
64 | ||
ae4735db | 65 | let print_parsing_stat_list ?(verbose=false) = fun statxs -> |
485bce71 | 66 | let total = List.length statxs in |
ae4735db C |
67 | let perfect = |
68 | statxs | |
69 | +> List.filter (function | |
485bce71 | 70 | {have_timeout = false; bad = 0} -> true | _ -> false) |
ae4735db | 71 | +> List.length |
485bce71 C |
72 | in |
73 | ||
74 | if verbose then begin | |
75 | pr "\n\n\n---------------------------------------------------------------"; | |
76 | pr "pbs with files:"; | |
ae4735db C |
77 | statxs |
78 | +> List.filter (function | |
79 | | {have_timeout = true} -> true | |
80 | | {bad = n} when n > 0 -> true | |
485bce71 | 81 | | _ -> false) |
ae4735db C |
82 | +> List.iter (function |
83 | {filename = file; have_timeout = timeout; bad = n} -> | |
485bce71 C |
84 | pr (file ^ " " ^ (if timeout then "TIMEOUT" else i_to_s n)); |
85 | ); | |
86 | ||
87 | pr "\n\n\n"; | |
88 | pr "files with lots of tokens passed/commentized:"; | |
89 | let threshold_passed = 100 in | |
ae4735db C |
90 | statxs |
91 | +> List.filter (function | |
485bce71 C |
92 | | {commentized = n} when n > threshold_passed -> true |
93 | | _ -> false) | |
ae4735db C |
94 | +> List.iter (function |
95 | {filename = file; commentized = n} -> | |
485bce71 C |
96 | pr (file ^ " " ^ (i_to_s n)); |
97 | ); | |
98 | ||
99 | pr "\n\n\n---------------------------------------------------------------"; | |
100 | end; | |
101 | ||
102 | pr ( | |
103 | (sprintf "NB total files = %d; " total) ^ | |
104 | (sprintf "perfect = %d; " perfect) ^ | |
ae4735db C |
105 | (sprintf "pbs = %d; " (statxs +> List.filter (function |
106 | {have_timeout = b; bad = n} when n > 0 -> true | _ -> false) | |
485bce71 | 107 | +> List.length)) ^ |
ae4735db C |
108 | (sprintf "timeout = %d; " (statxs +> List.filter (function |
109 | {have_timeout = true; bad = n} -> true | _ -> false) | |
485bce71 C |
110 | +> List.length)) ^ |
111 | (sprintf "=========> %d" ((100 * perfect) / total)) ^ "%" | |
ae4735db | 112 | |
485bce71 C |
113 | ); |
114 | let good = statxs +> List.fold_left (fun acc {correct = x} -> acc+x) 0 in | |
115 | let bad = statxs +> List.fold_left (fun acc {bad = x} -> acc+x) 0 in | |
116 | let passed = statxs +> List.fold_left (fun acc {commentized = x} -> acc+x) 0 | |
117 | in | |
118 | let gf, badf = float_of_int good, float_of_int bad in | |
119 | let passedf = float_of_int passed in | |
120 | pr ( | |
121 | (sprintf "nb good = %d, nb passed = %d " good passed) ^ | |
113803cf | 122 | (sprintf "=========> %f" (100.0 *. (passedf /. gf)) ^ "% passed") |
485bce71 C |
123 | ); |
124 | pr ( | |
125 | (sprintf "nb good = %d, nb bad = %d " good bad) ^ | |
113803cf | 126 | (sprintf "=========> %f" (100.0 *. (gf /. (gf +. badf))) ^ "% good" |
485bce71 C |
127 | ) |
128 | ) | |
129 | ||
91eba41f C |
130 | (*****************************************************************************) |
131 | (* Recurring error diagnostic *) | |
132 | (*****************************************************************************) | |
133 | (* asked/inspired by reviewer of CC'09 *) | |
134 | ||
ae4735db | 135 | let lines_around_error_line ~context (file, line) = |
91eba41f | 136 | let arr = Common.cat_array file in |
ae4735db | 137 | |
91eba41f C |
138 | let startl = max 0 (line - context) in |
139 | let endl = min (Array.length arr) (line + context) in | |
ae4735db | 140 | let res = ref [] in |
91eba41f | 141 | |
ae4735db | 142 | for i = startl to endl -1 do |
91eba41f C |
143 | Common.push2 arr.(i) res |
144 | done; | |
145 | List.rev !res | |
146 | ||
147 | ||
148 | ||
ae4735db | 149 | let print_recurring_problematic_tokens xs = |
91eba41f | 150 | let h = Hashtbl.create 101 in |
ae4735db C |
151 | xs +> List.iter (fun x -> |
152 | let file = x.filename in | |
153 | x.problematic_lines +> List.iter (fun (xs, line_error) -> | |
154 | xs +> List.iter (fun s -> | |
91eba41f | 155 | Common.hupdate_default s |
ae4735db | 156 | (fun (old, example) -> old + 1, example) |
91eba41f C |
157 | (fun() -> 0, (file, line_error)) h; |
158 | ))); | |
159 | pr2_xxxxxxxxxxxxxxxxx(); | |
160 | pr2 ("maybe 10 most problematic tokens"); | |
161 | pr2_xxxxxxxxxxxxxxxxx(); | |
162 | Common.hash_to_list h | |
ae4735db | 163 | +> List.sort (fun (k1,(v1,_)) (k2,(v2,_)) -> compare v2 v1) |
91eba41f | 164 | +> Common.take_safe 10 |
ae4735db | 165 | +> List.iter (fun (k,(i, (file_ex, line_ex))) -> |
91eba41f C |
166 | pr2 (spf "%s: present in %d parsing errors" k i); |
167 | pr2 ("example: "); | |
168 | let lines = lines_around_error_line ~context:2 (file_ex, line_ex) in | |
169 | lines +> List.iter (fun s -> pr2 (" " ^ s)); | |
ae4735db | 170 | |
91eba41f C |
171 | ); |
172 | pr2_xxxxxxxxxxxxxxxxx(); | |
173 | () | |
174 | ||
ae4735db | 175 | |
91eba41f C |
176 | |
177 | ||
485bce71 C |
178 | (*****************************************************************************) |
179 | (* Stat *) | |
180 | (*****************************************************************************) | |
181 | ||
ae4735db | 182 | (* Those variables were written for CC09, to evaluate the need for |
91eba41f | 183 | * some of our heuristics and extensions. |
ae4735db C |
184 | * |
185 | * coupling: if you add a new var, modify also assoc_stat_number below | |
91eba41f | 186 | *) |
485bce71 C |
187 | |
188 | let nTypedefInfer = ref 0 | |
189 | ||
190 | let nIncludeGrammar = ref 0 | |
191 | let nIncludeHack = ref 0 | |
192 | ||
ae4735db C |
193 | let nIteratorGrammar = ref 0 |
194 | let nIteratorHeuristic = ref 0 | |
485bce71 C |
195 | |
196 | let nMacroTopDecl = ref 0 | |
197 | let nMacroStructDecl = ref 0 | |
198 | let nMacroDecl = ref 0 | |
199 | let nMacroStmt = ref 0 | |
200 | let nMacroString = ref 0 | |
201 | let nMacroHigherOrder = ref 0 (* actions *) | |
202 | let nMacrohigherTypeGrammar = ref 0 | |
203 | let nMacroAttribute = ref 0 | |
204 | ||
205 | let nIfdefTop = ref 0 | |
206 | let nIfdefStmt = ref 0 | |
207 | let nIfdefStruct = ref 0 | |
208 | let nIfdefInitializer = ref 0 | |
209 | (* nIfdefExpr, nIfdefType *) | |
210 | ||
211 | let nIfdefFunheader = ref 0 | |
212 | ||
213 | let nIfdefExprPassing = ref 0 | |
214 | let nIfdefPassing = ref 0 | |
215 | ||
216 | let nIncludePassing = ref 0 | |
3a314143 | 217 | let nUndefPassing = ref 0 |
485bce71 C |
218 | let nDefinePassing = ref 0 |
219 | ||
220 | let nIfdefZero = ref 0 | |
221 | let nIfdefVersion = ref 0 | |
222 | ||
223 | ||
224 | ||
225 | let nGccTypeof = ref 0 | |
226 | let nGccLongLong = ref 0 | |
227 | let nGccAsm = ref 0 | |
228 | let nGccInline = ref 0 | |
229 | let nGccAttribute = ref 0 | |
230 | let nGccCaseRange = ref 0 | |
231 | let nGccMixDecl = ref 0 | |
232 | let nGccDesignator = ref 0 | |
233 | let nGccStmtExpr = ref 0 | |
234 | let nGccConstructor = ref 0 | |
235 | let nGccEmptyStruct = ref 0 | |
236 | let nGccNestedFunc = ref 0 | |
237 | ||
238 | let nGccMisc = ref 0 | |
239 | ||
240 | ||
241 | ||
242 | let nDefineHack = ref 0 | |
243 | ||
244 | let nDefineConstant = ref 0 | |
245 | let nDefineStmt = ref 0 | |
246 | let nDefineExpr = ref 0 | |
247 | (* both below require some heuristic support *) | |
248 | let nDefineWhile0 = ref 0 | |
249 | let nDefineInit = ref 0 | |
250 | ||
251 | let nDefineOther = ref 0 | |
252 | ||
253 | let nUndef = ref 0 | |
254 | let nPragmaAndCo = ref 0 | |
255 | ||
256 | (* let nDirectiveTop = ref 0 *) | |
257 | let nDirectiveStmt = ref 0 | |
258 | let nDirectiveStruct = ref 0 | |
259 | let nDirectiveInitializer = ref 0 | |
260 | ||
261 | ||
262 | (* from standard.h *) | |
263 | let nMacroHint = ref 0 | |
264 | let nMacroExpand = ref 0 | |
265 | ||
266 | let nNotParsedCorrectly = ref 0 | |
267 | ||
ae4735db | 268 | let assoc_stat_number = |
485bce71 C |
269 | [ |
270 | "nTypedefInfer", nTypedefInfer; | |
271 | ||
272 | "nIteratorHeuristic", nIteratorHeuristic; | |
273 | ||
274 | "nMacroTopDecl", nMacroTopDecl; | |
275 | "nMacroStructDecl", nMacroStructDecl; | |
276 | "nMacroDecl", nMacroDecl; | |
277 | "nMacroStmt", nMacroStmt; | |
278 | "nMacroString", nMacroString; | |
279 | "nMacroHigherOrder", nMacroHigherOrder; | |
280 | "nMacroAttribute", nMacroAttribute; | |
281 | ||
282 | "nMacrohigherTypeGrammar", nMacrohigherTypeGrammar; | |
283 | ||
284 | "nIfdefTop", nIfdefTop; | |
285 | "nIfdefStmt", nIfdefStmt; | |
286 | "nIfdefStruct", nIfdefStruct; | |
287 | "nIfdefInitializer", nIfdefInitializer; | |
288 | ||
289 | "nIfdefFunheader", nIfdefFunheader; | |
290 | "nIfdefZero", nIfdefZero; | |
291 | "nIfdefVersion", nIfdefVersion; | |
292 | "nIfdefExprPassing", nIfdefExprPassing; | |
293 | "nIfdefPassing", nIfdefPassing; | |
294 | ||
295 | "nIncludePassing", nIncludePassing; | |
296 | "nDefinePassing", nDefinePassing; | |
3a314143 | 297 | "nUndefPassing", nUndefPassing; |
485bce71 C |
298 | |
299 | "nMacroExpand", nMacroExpand; | |
300 | "nMacroHint", nMacroHint; | |
301 | ||
302 | ||
303 | "nGccTypeof", nGccTypeof; | |
304 | "nGccLongLong", nGccLongLong; | |
305 | "nGccAsm", nGccAsm; | |
306 | "nGccInline", nGccInline; | |
307 | "nGccAttribute", nGccAttribute; | |
308 | "nGccCaseRange", nGccCaseRange; | |
309 | "nGccMixDecl", nGccMixDecl; | |
310 | "nGccDesignator", nGccDesignator; | |
311 | "nGccStmtExpr", nGccStmtExpr; | |
312 | "nGccConstructor", nGccConstructor; | |
313 | "nGccEmptyStruct", nGccEmptyStruct; | |
314 | "nGccNestedFunc", nGccNestedFunc; | |
315 | ||
316 | "nGccMisc", nGccMisc; | |
317 | ||
318 | ||
319 | "nDefineHack", nDefineHack; | |
320 | ||
321 | "nDefineConstant", nDefineConstant; | |
322 | "nDefineStmt", nDefineStmt; | |
323 | "nDefineExpr", nDefineExpr; | |
324 | "nDefineInit", nDefineInit; | |
325 | "nDefineOther", nDefineOther; | |
326 | ||
327 | "nUndef", nUndef; | |
328 | "nPragmaAndCo", nPragmaAndCo; | |
329 | ||
330 | "nDirectiveStmt", nDirectiveStmt; | |
331 | "nDirectiveStruct", nDirectiveStruct; | |
332 | "nDirectiveInitializer", nDirectiveInitializer; | |
333 | ||
334 | "nNotParsedCorrectly", nNotParsedCorrectly; | |
335 | ||
336 | ||
337 | (* less *) | |
338 | "nIncludeGrammar", nIncludeGrammar; | |
339 | "nIncludeHack", nIncludeHack; | |
340 | ||
341 | "nIteratorGrammar", nIteratorGrammar; | |
342 | ] | |
343 | ||
ae4735db C |
344 | let print_stat_numbers () = |
345 | assoc_stat_number +> List.iter (fun (k, vref) -> | |
485bce71 C |
346 | pr2 (spf "%-30s -> %d" k !vref); |
347 | ) |