71 |
76 |
72 fun random_range l h = |
77 fun random_range l h = |
73 if h < l orelse l < 0 then raise RANDOM |
78 if h < l orelse l < 0 then raise RANDOM |
74 else l + Real.floor (rmod (random ()) (real (h - l + 1))); |
79 else l + Real.floor (rmod (random ()) (real (h - l + 1))); |
75 |
80 |
76 datatype outcome = GenuineCex | PotentialCex | NoCex | Donno | Timeout | Error |
81 fun take_random 0 _ = [] |
|
82 | take_random _ [] = [] |
|
83 | take_random n xs = |
|
84 let val j = random_range 0 (length xs - 1) in |
|
85 Library.nth xs j :: take_random (n - 1) (nth_drop j xs) |
|
86 end |
|
87 |
|
88 (* possible outcomes *) |
|
89 |
|
90 datatype outcome = GenuineCex | PotentialCex | NoCex | Donno | Timeout | Error | Solved | Unsolved |
|
91 |
|
92 fun string_of_outcome GenuineCex = "GenuineCex" |
|
93 | string_of_outcome PotentialCex = "PotentialCex" |
|
94 | string_of_outcome NoCex = "NoCex" |
|
95 | string_of_outcome Donno = "Donno" |
|
96 | string_of_outcome Timeout = "Timeout" |
|
97 | string_of_outcome Error = "Error" |
|
98 | string_of_outcome Solved = "Solved" |
|
99 | string_of_outcome Unsolved = "Unsolved" |
|
100 |
77 type timing = (string * int) list |
101 type timing = (string * int) list |
78 |
102 |
79 type mtd = string * (theory -> term -> outcome * (timing * (int * Quickcheck.report list) list option)) |
103 type mtd = string * (theory -> term -> outcome * (timing * (int * Quickcheck.report list) list option)) |
80 |
104 |
81 type mutant_subentry = term * (string * (outcome * (timing * Quickcheck.report option))) list |
105 type mutant_subentry = term * (string * (outcome * (timing * Quickcheck.report option))) list |
83 |
107 |
84 type subentry = string * int * int * int * int * int * int |
108 type subentry = string * int * int * int * int * int * int |
85 type entry = string * bool * subentry list |
109 type entry = string * bool * subentry list |
86 type report = entry list |
110 type report = entry list |
87 |
111 |
88 fun inst_type insts (Type (s, Ts)) = Type (s, map (inst_type insts) Ts) |
112 (* possible invocations *) |
89 | inst_type insts T = the_default HOLogic.intT (AList.lookup op = insts T) |
113 |
90 |
114 (** quickcheck **) |
91 fun preprocess thy insts t = Object_Logic.atomize_term thy |
115 |
92 (map_types (inst_type insts) (Mutabelle.freeze t)); |
116 fun invoke_quickcheck change_options quickcheck_generator thy t = |
93 |
|
94 fun invoke_quickcheck quickcheck_generator thy t = |
|
95 TimeLimit.timeLimit (Time.fromSeconds (!Auto_Tools.time_limit)) |
117 TimeLimit.timeLimit (Time.fromSeconds (!Auto_Tools.time_limit)) |
96 (fn _ => |
118 (fn _ => |
97 case Quickcheck.test_term (ProofContext.init_global thy) |
119 case Quickcheck.test_goal_terms (change_options (ProofContext.init_global thy)) |
98 (SOME quickcheck_generator) (preprocess thy [] t) of |
120 (SOME quickcheck_generator, []) [t] of |
99 (NONE, (time_report, report)) => (NoCex, (time_report, report)) |
121 (NONE, _) => (NoCex, ([], NONE)) |
100 | (SOME _, (time_report, report)) => (GenuineCex, (time_report, report))) () |
122 | (SOME _, _) => (GenuineCex, ([], NONE))) () |
101 handle TimeLimit.TimeOut => (Timeout, ([("timelimit", !Auto_Tools.time_limit)], NONE)) |
123 handle TimeLimit.TimeOut => (Timeout, ([("timelimit", !Auto_Tools.time_limit)], NONE)) |
102 |
124 |
103 fun quickcheck_mtd quickcheck_generator = |
125 fun quickcheck_mtd change_options quickcheck_generator = |
104 ("quickcheck_" ^ quickcheck_generator, invoke_quickcheck quickcheck_generator) |
126 ("quickcheck_" ^ quickcheck_generator, invoke_quickcheck change_options quickcheck_generator) |
105 |
127 |
106 (* |
128 (** solve direct **) |
|
129 |
|
130 fun invoke_solve_direct thy t = |
|
131 let |
|
132 val state = Proof.theorem NONE (K I) (map (single o rpair []) [t]) (ProofContext.init_global thy) |
|
133 in |
|
134 case Solve_Direct.solve_direct false state of |
|
135 (true, _) => (Solved, ([], NONE)) |
|
136 | (false, _) => (Unsolved, ([], NONE)) |
|
137 end |
|
138 |
|
139 val solve_direct_mtd = ("solve_direct", invoke_solve_direct) |
|
140 |
|
141 (** try **) |
|
142 |
|
143 fun invoke_try thy t = |
|
144 let |
|
145 val state = Proof.theorem NONE (K I) (map (single o rpair []) [t]) (ProofContext.init_global thy) |
|
146 in |
|
147 case Try.invoke_try NONE state of |
|
148 true => (Solved, ([], NONE)) |
|
149 | false => (Unsolved, ([], NONE)) |
|
150 end |
|
151 |
|
152 val try_mtd = ("try", invoke_try) |
|
153 |
|
154 (* |
107 fun invoke_refute thy t = |
155 fun invoke_refute thy t = |
108 let |
156 let |
109 val res = MyRefute.refute_term thy [] t |
157 val res = MyRefute.refute_term thy [] t |
110 val _ = Output.urgent_message ("Refute: " ^ res) |
158 val _ = Output.urgent_message ("Refute: " ^ res) |
111 in |
159 in |
198 (@{const_name "HOL.simp_implies"}, "prop => prop => prop"), |
248 (@{const_name "HOL.simp_implies"}, "prop => prop => prop"), |
199 (@{const_name "bot_fun_inst.bot_fun"}, "'a"), |
249 (@{const_name "bot_fun_inst.bot_fun"}, "'a"), |
200 (@{const_name "top_fun_inst.top_fun"}, "'a"), |
250 (@{const_name "top_fun_inst.top_fun"}, "'a"), |
201 (@{const_name "Pure.term"}, "'a"), |
251 (@{const_name "Pure.term"}, "'a"), |
202 (@{const_name "top_class.top"}, "'a"), |
252 (@{const_name "top_class.top"}, "'a"), |
203 (@{const_name "HOL.equal"}, "'a"), |
|
204 (@{const_name "Quotient.Quot_True"}, "'a")(*, |
253 (@{const_name "Quotient.Quot_True"}, "'a")(*, |
205 (@{const_name "uminus"}, "'a"), |
254 (@{const_name "uminus"}, "'a"), |
206 (@{const_name "Nat.size"}, "'a"), |
255 (@{const_name "Nat.size"}, "'a"), |
207 (@{const_name "Groups.abs"}, "'a") *)] |
256 (@{const_name "Groups.abs"}, "'a") *)] |
208 |
257 |
209 val forbidden_thms = |
258 val forbidden_thms = |
210 ["finite_intvl_succ_class", |
259 ["finite_intvl_succ_class", |
211 "nibble"] |
260 "nibble"] |
212 |
261 |
213 val forbidden_consts = |
262 val forbidden_consts = |
214 [@{const_name nibble_pair_of_char}] |
263 [@{const_name nibble_pair_of_char}, @{const_name "TYPE"}] |
215 |
264 |
216 fun is_forbidden_theorem (s, th) = |
265 fun is_forbidden_theorem (s, th) = |
217 let val consts = Term.add_const_names (prop_of th) [] in |
266 let val consts = Term.add_const_names (prop_of th) [] in |
218 exists (member (op =) (space_explode "." s)) forbidden_thms orelse |
267 exists (member (op =) (space_explode "." s)) forbidden_thms orelse |
219 exists (member (op =) forbidden_consts) consts orelse |
268 exists (member (op =) forbidden_consts) consts orelse |
220 length (space_explode "." s) <> 2 orelse |
269 length (space_explode "." s) <> 2 orelse |
221 String.isPrefix "type_definition" (List.last (space_explode "." s)) orelse |
270 String.isPrefix "type_definition" (List.last (space_explode "." s)) orelse |
222 String.isSuffix "_def" s orelse |
271 String.isSuffix "_def" s orelse |
223 String.isSuffix "_raw" s |
272 String.isSuffix "_raw" s orelse |
|
273 String.isPrefix "term_of" (List.last (space_explode "." s)) |
224 end |
274 end |
225 |
275 |
226 val forbidden_mutant_constnames = |
276 val forbidden_mutant_constnames = |
227 ["HOL.induct_equal", |
277 ["HOL.induct_equal", |
228 "HOL.induct_implies", |
278 "HOL.induct_implies", |
233 @{const_name "HOL.simp_implies"}, |
283 @{const_name "HOL.simp_implies"}, |
234 @{const_name "bot_fun_inst.bot_fun"}, |
284 @{const_name "bot_fun_inst.bot_fun"}, |
235 @{const_name "top_fun_inst.top_fun"}, |
285 @{const_name "top_fun_inst.top_fun"}, |
236 @{const_name "Pure.term"}, |
286 @{const_name "Pure.term"}, |
237 @{const_name "top_class.top"}, |
287 @{const_name "top_class.top"}, |
238 @{const_name "HOL.equal"}, |
288 (*@{const_name "HOL.equal"},*) |
239 @{const_name "Quotient.Quot_True"}] |
289 @{const_name "Quotient.Quot_True"} |
|
290 (*@{const_name "==>"}, @{const_name "=="}*)] |
|
291 |
|
292 val forbidden_mutant_consts = |
|
293 [ |
|
294 (@{const_name "Groups.zero_class.zero"}, @{typ "prop => prop => prop"}), |
|
295 (@{const_name "Groups.one_class.one"}, @{typ "prop => prop => prop"}), |
|
296 (@{const_name "Groups.plus_class.plus"}, @{typ "prop => prop => prop"}), |
|
297 (@{const_name "Groups.minus_class.minus"}, @{typ "prop => prop => prop"}), |
|
298 (@{const_name "Groups.times_class.times"}, @{typ "prop => prop => prop"}), |
|
299 (@{const_name "Rings.inverse_class.divide"}, @{typ "prop => prop => prop"}), |
|
300 (@{const_name "Lattices.semilattice_inf_class.inf"}, @{typ "prop => prop => prop"}), |
|
301 (@{const_name "Lattices.semilattice_sup_class.sup"}, @{typ "prop => prop => prop"}), |
|
302 (@{const_name "Orderings.bot_class.bot"}, @{typ "prop => prop => prop"}), |
|
303 (@{const_name "Orderings.ord_class.min"}, @{typ "prop => prop => prop"}), |
|
304 (@{const_name "Orderings.ord_class.max"}, @{typ "prop => prop => prop"}), |
|
305 (@{const_name "Divides.div_class.mod"}, @{typ "prop => prop => prop"}), |
|
306 (@{const_name "Divides.div_class.div"}, @{typ "prop => prop => prop"}), |
|
307 (@{const_name "GCD.gcd_class.gcd"}, @{typ "prop => prop => prop"}), |
|
308 (@{const_name "GCD.gcd_class.lcm"}, @{typ "prop => prop => prop"}), |
|
309 (@{const_name "Orderings.bot_class.bot"}, @{typ "bool => prop"}), |
|
310 (@{const_name "Groups.one_class.one"}, @{typ "bool => prop"}), |
|
311 (@{const_name "Groups.zero_class.zero"},@{typ "bool => prop"})] |
240 |
312 |
241 fun is_forbidden_mutant t = |
313 fun is_forbidden_mutant t = |
242 let |
314 let |
243 val consts = Term.add_const_names t [] |
315 val const_names = Term.add_const_names t [] |
244 in |
316 val consts = Term.add_consts t [] |
245 exists (String.isPrefix "Nitpick") consts orelse |
317 in |
246 exists (String.isSubstring "_sumC") consts orelse |
318 exists (String.isPrefix "Nitpick") const_names orelse |
247 exists (member (op =) forbidden_mutant_constnames) consts |
319 exists (String.isSubstring "_sumC") const_names orelse |
248 end |
320 exists (member (op =) forbidden_mutant_constnames) const_names orelse |
|
321 exists (member (op =) forbidden_mutant_consts) consts |
|
322 end |
|
323 |
|
324 (* executable via quickcheck *) |
249 |
325 |
250 fun is_executable_term thy t = |
326 fun is_executable_term thy t = |
251 can (TimeLimit.timeLimit (seconds 2.0) |
327 let |
252 (Quickcheck.test_term |
328 val ctxt = ProofContext.init_global thy |
253 (Context.proof_map (Quickcheck.map_test_params (apfst (K (1, 0)))) (ProofContext.init_global thy)) |
329 in |
254 (SOME "SML"))) (preprocess thy [] t) |
330 can (TimeLimit.timeLimit (seconds 2.0) |
|
331 (Quickcheck.test_goal_terms |
|
332 ((Config.put Quickcheck.finite_types true #> |
|
333 Config.put Quickcheck.size 1 #> Config.put Quickcheck.iterations 1) ctxt) |
|
334 (SOME "random" , []))) (map (Object_Logic.atomize_term thy) (fst (Variable.import_terms true [t] ctxt))) |
|
335 end |
255 |
336 |
256 fun is_executable_thm thy th = is_executable_term thy (prop_of th) |
337 fun is_executable_thm thy th = is_executable_term thy (prop_of th) |
257 |
338 |
258 val freezeT = |
339 val freezeT = |
259 map_types (map_type_tvar (fn ((a, i), S) => |
340 map_types (map_type_tvar (fn ((a, i), S) => |
265 (* andalso is_executable_thm thy th *)) |
346 (* andalso is_executable_thm thy th *)) |
266 (map snd (filter_out is_forbidden_theorem (Mutabelle.all_unconcealed_thms_of thy))) |
347 (map snd (filter_out is_forbidden_theorem (Mutabelle.all_unconcealed_thms_of thy))) |
267 |
348 |
268 val count = length oo filter o equal |
349 val count = length oo filter o equal |
269 |
350 |
270 fun take_random 0 _ = [] |
|
271 | take_random _ [] = [] |
|
272 | take_random n xs = |
|
273 let val j = random_range 0 (length xs - 1) in |
|
274 Library.nth xs j :: take_random (n - 1) (nth_drop j xs) |
|
275 end |
|
276 |
|
277 fun cpu_time description f = |
351 fun cpu_time description f = |
278 let |
352 let |
279 val start = start_timing () |
353 val start = start_timing () |
280 val result = Exn.capture f () |
354 val result = Exn.capture f () |
281 val time = Time.toMilliseconds (#cpu (end_timing start)) |
355 val time = Time.toMilliseconds (#cpu (end_timing start)) |
282 in (Exn.release result, (description, time)) end |
356 in (Exn.release result, (description, time)) end |
283 |
357 (* |
|
358 fun unsafe_invoke_mtd thy (mtd_name, invoke_mtd) t = |
|
359 let |
|
360 val _ = Output.urgent_message ("Invoking " ^ mtd_name) |
|
361 val ((res, (timing, reports)), time) = cpu_time "total time" (fn () => invoke_mtd thy t |
|
362 handle ERROR s => (tracing s; (Error, ([], NONE)))) |
|
363 val _ = Output.urgent_message (" Done") |
|
364 in (res, (time :: timing, reports)) end |
|
365 *) |
284 fun safe_invoke_mtd thy (mtd_name, invoke_mtd) t = |
366 fun safe_invoke_mtd thy (mtd_name, invoke_mtd) t = |
285 let |
367 let |
286 val _ = Output.urgent_message ("Invoking " ^ mtd_name) |
368 val _ = Output.urgent_message ("Invoking " ^ mtd_name) |
287 val ((res, (timing, reports)), time) = cpu_time "total time" |
369 val (res, (timing, reports)) = (*cpu_time "total time" |
288 (fn () => case try (invoke_mtd thy) t of |
370 (fn () => *)case try (invoke_mtd thy) t of |
289 SOME (res, (timing, reports)) => (res, (timing, reports)) |
371 SOME (res, (timing, reports)) => (res, (timing, reports)) |
290 | NONE => (Output.urgent_message ("**** PROBLEMS WITH " ^ Syntax.string_of_term_global thy t); |
372 | NONE => (Output.urgent_message ("**** PROBLEMS WITH " ^ Syntax.string_of_term_global thy t); |
291 (Error , ([], NONE)))) |
373 (Error, ([], NONE))) |
292 val _ = Output.urgent_message (" Done") |
374 val _ = Output.urgent_message (" Done") |
293 in (res, (time :: timing, reports)) end |
375 in (res, (timing, reports)) end |
294 |
376 |
295 (* theory -> term list -> mtd -> subentry *) |
377 (* theory -> term list -> mtd -> subentry *) |
296 (* |
378 |
297 fun test_mutants_using_one_method thy mutants (mtd_name, invoke_mtd) = |
379 fun test_mutants_using_one_method thy mutants (mtd_name, invoke_mtd) = |
298 let |
380 let |
299 val res = map (safe_invoke_mtd thy (mtd_name, invoke_mtd)) mutants |
381 val res = map (fst o safe_invoke_mtd thy (mtd_name, invoke_mtd)) mutants |
300 in |
382 in |
301 (mtd_name, count GenuineCex res, count PotentialCex res, count NoCex res, |
383 (mtd_name, count GenuineCex res, count PotentialCex res, count NoCex res, |
302 count Donno res, count Timeout res, count Error res) |
384 count Donno res, count Timeout res, count Error res) |
303 end |
385 end |
304 |
386 |
|
387 (* creating entries *) |
|
388 |
305 fun create_entry thy thm exec mutants mtds = |
389 fun create_entry thy thm exec mutants mtds = |
306 (Thm.get_name_hint thm, exec, map (test_mutants_using_one_method thy mutants) mtds) |
390 (Thm.get_name_hint thm, exec, map (test_mutants_using_one_method thy mutants) mtds) |
307 *) |
391 |
308 fun create_detailed_entry thy thm exec mutants mtds = |
392 fun create_detailed_entry thy thm exec mutants mtds = |
309 let |
393 let |
310 fun create_mutant_subentry mutant = (mutant, |
394 fun create_mutant_subentry mutant = (mutant, |
311 map (fn (mtd_name, invoke_mtd) => |
395 map (fn (mtd_name, invoke_mtd) => |
312 (mtd_name, safe_invoke_mtd thy (mtd_name, invoke_mtd) mutant)) mtds) |
396 (mtd_name, safe_invoke_mtd thy (mtd_name, invoke_mtd) mutant)) mtds) |
342 val mutants = mutants |
427 val mutants = mutants |
343 |> take_random max_mutants |
428 |> take_random max_mutants |
344 |> map Mutabelle.freeze |> map freezeT |
429 |> map Mutabelle.freeze |> map freezeT |
345 (* |> filter (not o is_forbidden_mutant) *) |
430 (* |> filter (not o is_forbidden_mutant) *) |
346 |> List.mapPartial (try (Sign.cert_term thy)) |
431 |> List.mapPartial (try (Sign.cert_term thy)) |
|
432 |> List.filter (is_some o try (cterm_of thy)) |
347 val _ = map (fn t => Output.urgent_message ("MUTANT: " ^ Syntax.string_of_term_global thy t)) mutants |
433 val _ = map (fn t => Output.urgent_message ("MUTANT: " ^ Syntax.string_of_term_global thy t)) mutants |
348 in |
434 in |
349 create_entry thy thm exec mutants mtds |
435 create_entry thy thm exec mutants mtds |
350 end |
436 end |
351 |
437 |
352 (* theory -> mtd list -> thm list -> report *) |
438 (* theory -> mtd list -> thm list -> report *) |
353 val mutate_theorems = map ooo mutate_theorem |
439 val mutate_theorems = map ooo mutate_theorem |
354 |
|
355 fun string_of_outcome GenuineCex = "GenuineCex" |
|
356 | string_of_outcome PotentialCex = "PotentialCex" |
|
357 | string_of_outcome NoCex = "NoCex" |
|
358 | string_of_outcome Donno = "Donno" |
|
359 | string_of_outcome Timeout = "Timeout" |
|
360 | string_of_outcome Error = "Error" |
|
361 |
440 |
362 fun string_of_mutant_subentry thy thm_name (t, results) = |
441 fun string_of_mutant_subentry thy thm_name (t, results) = |
363 "mutant: " ^ Syntax.string_of_term_global thy t ^ "\n" ^ |
442 "mutant: " ^ Syntax.string_of_term_global thy t ^ "\n" ^ |
364 space_implode "; " |
443 space_implode "; " |
365 (map (fn (mtd_name, (outcome, timing)) => mtd_name ^ ": " ^ string_of_outcome outcome) results) ^ |
444 (map (fn (mtd_name, (outcome, timing)) => mtd_name ^ ": " ^ string_of_outcome outcome) results) ^ |
376 fun string_of_reports NONE = "" |
455 fun string_of_reports NONE = "" |
377 | string_of_reports (SOME reports) = |
456 | string_of_reports (SOME reports) = |
378 cat_lines (map (fn (size, [report]) => |
457 cat_lines (map (fn (size, [report]) => |
379 "size " ^ string_of_int size ^ ": " ^ string_of_report report) (rev reports)) |
458 "size " ^ string_of_int size ^ ": " ^ string_of_report report) (rev reports)) |
380 fun string_of_mtd_result (mtd_name, (outcome, (timing, reports))) = |
459 fun string_of_mtd_result (mtd_name, (outcome, (timing, reports))) = |
381 mtd_name ^ ": " ^ string_of_outcome outcome ^ "; " ^ |
460 mtd_name ^ ": " ^ string_of_outcome outcome |
382 space_implode "; " (map (fn (s, t) => (s ^ ": " ^ string_of_int t)) timing) |
461 (*" with time " ^ " (" ^ space_implode "; " (map (fn (s, t) => (s ^ ": " ^ string_of_int t)) timing) ^ ")"*) |
383 (*^ "\n" ^ string_of_reports reports*) |
462 (*^ "\n" ^ string_of_reports reports*) |
384 in |
463 in |
385 "mutant of " ^ thm_name ^ ":\n" |
464 "mutant of " ^ thm_name ^ ":\n" |
386 ^ unyxml (Syntax.string_of_term_global thy t) ^ "\n" ^ cat_lines (map string_of_mtd_result results) |
465 ^ unyxml (Syntax.string_of_term_global thy t) ^ "\n" ^ space_implode "; " (map string_of_mtd_result results) |
387 end |
466 end |
388 |
467 |
389 fun string_of_detailed_entry thy (thm_name, exec, t, mutant_subentries) = |
468 fun string_of_detailed_entry thy (thm_name, exec, t, mutant_subentries) = |
390 thm_name ^ " " ^ (if exec then "[exe]" else "[noexe]") ^ ": " ^ |
469 thm_name ^ " " ^ (if exec then "[exe]" else "[noexe]") ^ ": " ^ |
391 Syntax.string_of_term_global thy t ^ "\n" ^ |
470 Syntax.string_of_term_global thy t ^ "\n" ^ |
392 cat_lines (map (string_of_mutant_subentry' thy thm_name) mutant_subentries) ^ "\n" |
471 cat_lines (map (string_of_mutant_subentry' thy thm_name) mutant_subentries) ^ "\n" |
393 |
472 |
394 fun theoryfile_string_of_mutant_subentry thy thm_name (i, (t, results)) = |
473 fun theoryfile_string_of_mutant_subentry thy thm_name (i, (t, results)) = |
395 "lemma " ^ thm_name ^ "_" ^ string_of_int (i + 1) ^ ":\n" ^ |
474 "lemma " ^ thm_name ^ "_" ^ string_of_int (i + 1) ^ ":\n" ^ |
396 "\"" ^ unyxml (Syntax.string_of_term_global thy t) ^ |
475 "\"" ^ unyxml (Syntax.string_of_term_global thy t) ^ |
397 "\" \nquickcheck[generator = SML]\nquickcheck[generator = predicate_compile_wo_ff]\n" ^ |
476 "\" \nquickcheck\noops\n" |
398 "quickcheck[generator = predicate_compile_ff_nofs]\noops\n" |
|
399 |
477 |
400 fun theoryfile_string_of_detailed_entry thy (thm_name, exec, t, mutant_subentries) = |
478 fun theoryfile_string_of_detailed_entry thy (thm_name, exec, t, mutant_subentries) = |
401 "subsubsection {* mutants of " ^ thm_name ^ " *}\n\n" ^ |
479 "subsubsection {* mutants of " ^ thm_name ^ " *}\n\n" ^ |
402 cat_lines (map_index |
480 cat_lines (map_index |
403 (theoryfile_string_of_mutant_subentry thy thm_name) mutant_subentries) ^ "\n" |
481 (theoryfile_string_of_mutant_subentry thy thm_name) mutant_subentries) ^ "\n" |
407 timeout, error) = |
485 timeout, error) = |
408 " " ^ mtd_name ^ ": " ^ Int.toString genuine_cex ^ "+ " ^ |
486 " " ^ mtd_name ^ ": " ^ Int.toString genuine_cex ^ "+ " ^ |
409 Int.toString potential_cex ^ "= " ^ Int.toString no_cex ^ "- " ^ |
487 Int.toString potential_cex ^ "= " ^ Int.toString no_cex ^ "- " ^ |
410 Int.toString donno ^ "? " ^ Int.toString timeout ^ "T " ^ |
488 Int.toString donno ^ "? " ^ Int.toString timeout ^ "T " ^ |
411 Int.toString error ^ "!" |
489 Int.toString error ^ "!" |
|
490 |
412 (* entry -> string *) |
491 (* entry -> string *) |
413 fun string_for_entry (thm_name, exec, subentries) = |
492 fun string_for_entry (thm_name, exec, subentries) = |
414 thm_name ^ " " ^ (if exec then "[exe]" else "[noexe]") ^ ":\n" ^ |
493 thm_name ^ " " ^ (if exec then "[exe]" else "[noexe]") ^ ":\n" ^ |
415 cat_lines (map string_for_subentry subentries) ^ "\n" |
494 cat_lines (map string_for_subentry subentries) ^ "\n" |
|
495 |
416 (* report -> string *) |
496 (* report -> string *) |
417 fun string_for_report report = cat_lines (map string_for_entry report) |
497 fun string_for_report report = cat_lines (map string_for_entry report) |
418 |
498 |
419 (* string -> report -> unit *) |
499 (* string -> report -> unit *) |
420 fun write_report file_name = |
500 fun write_report file_name = |
422 |
502 |
423 (* theory -> mtd list -> thm list -> string -> unit *) |
503 (* theory -> mtd list -> thm list -> string -> unit *) |
424 fun mutate_theorems_and_write_report thy mtds thms file_name = |
504 fun mutate_theorems_and_write_report thy mtds thms file_name = |
425 let |
505 let |
426 val _ = Output.urgent_message "Starting Mutabelle..." |
506 val _ = Output.urgent_message "Starting Mutabelle..." |
427 val Quickcheck.Test_Params test_params = Quickcheck.test_params_of (ProofContext.init_global thy) |
507 val ctxt = ProofContext.init_global thy |
428 val path = Path.explode file_name |
508 val path = Path.explode file_name |
429 (* for normal report: *) |
509 (* for normal report: *) |
430 (*val (gen_create_entry, gen_string_for_entry) = (create_entry, string_for_entry)*) |
510 (* |
431 (*for detailled report: *) |
511 val (gen_create_entry, gen_string_for_entry) = (create_entry, string_for_entry) |
432 val (gen_create_entry, gen_string_for_entry) = |
512 *) |
433 (create_detailed_entry, string_of_detailed_entry thy) |
513 (* for detailled report: *) |
434 val (gen_create_entry, gen_string_for_entry) = |
514 val (gen_create_entry, gen_string_for_entry) = (create_detailed_entry, string_of_detailed_entry thy) |
435 (create_detailed_entry, theoryfile_string_of_detailed_entry thy) |
515 (* for theory creation: *) |
|
516 (*val (gen_create_entry, gen_string_for_entry) = (create_detailed_entry, theoryfile_string_of_detailed_entry thy)*) |
436 in |
517 in |
437 File.write path ( |
518 File.write path ( |
438 "Mutation options = " ^ |
519 "Mutation options = " ^ |
439 "max_mutants: " ^ string_of_int max_mutants ^ |
520 "max_mutants: " ^ string_of_int max_mutants ^ |
440 "; num_mutations: " ^ string_of_int num_mutations ^ "\n" ^ |
521 "; num_mutations: " ^ string_of_int num_mutations ^ "\n" ^ |
441 "QC options = " ^ |
522 "QC options = " ^ |
442 (*"quickcheck_generator: " ^ quickcheck_generator ^ ";*) |
523 (*"quickcheck_generator: " ^ quickcheck_generator ^ ";*) |
443 "size: " ^ string_of_int (#size test_params) ^ |
524 "size: " ^ string_of_int (Config.get ctxt Quickcheck.size) ^ |
444 "; iterations: " ^ string_of_int (#iterations test_params) ^ "\n"); |
525 "; iterations: " ^ string_of_int (Config.get ctxt Quickcheck.iterations) ^ "\n"); |
445 map (File.append path o gen_string_for_entry o mutate_theorem gen_create_entry thy mtds) thms; |
526 map (File.append path o gen_string_for_entry o mutate_theorem gen_create_entry thy mtds) thms; |
446 () |
527 () |
447 end |
528 end |
448 |
529 |
449 end; |
530 end; |