src/Tools/quickcheck.ML
changeset 39253 0c47d615a69b
parent 39252 8f176e575a49
child 39324 05452dd66b2b
--- a/src/Tools/quickcheck.ML	Thu Sep 09 16:43:57 2010 +0200
+++ b/src/Tools/quickcheck.ML	Thu Sep 09 17:23:03 2010 +0200
@@ -18,11 +18,13 @@
   { size: int, iterations: int, default_type: typ list, no_assms: bool,
     expect : expectation, report: bool, quiet : bool};
   val test_params_of: Proof.context -> test_params 
+  val report : Proof.context -> bool
+  val set_reporting : bool -> Proof.context -> Proof.context
   val add_generator:
-    string * (Proof.context -> bool -> term -> int -> term list option * (bool list * bool))
+    string * (Proof.context -> term -> int -> term list option * (bool list * bool))
       -> Context.generic -> Context.generic
   (* testing terms and proof states *)
-  val gen_test_term: Proof.context -> bool -> bool -> string option -> int -> int -> term ->
+  val gen_test_term: Proof.context -> bool -> string option -> int -> int -> term ->
     (string * term) list option * ((string * int) list * ((int * report list) list) option)
   val test_term: Proof.context -> bool -> string option -> int -> int -> term ->
     (string * term) list option
@@ -102,7 +104,7 @@
 structure Data = Generic_Data
 (
   type T =
-    (string * (Proof.context -> bool -> term -> int -> term list option * (bool list * bool))) list
+    (string * (Proof.context -> term -> int -> term list option * (bool list * bool))) list
       * test_params;
   val empty = ([], Test_Params
     { size = 10, iterations = 100, default_type = [], no_assms = false,
@@ -115,6 +117,13 @@
 
 val test_params_of = snd o Data.get o Context.Proof;
 
+val report = snd o fst o snd o snd o dest_test_params o test_params_of
+
+fun map_report f (Test_Params { size, iterations, default_type, no_assms, expect, report, quiet }) =
+  make_test_params ((size, iterations), ((default_type, no_assms), ((expect, f report), quiet)));
+
+fun set_reporting report = Context.proof_map (Data.map (apsnd (map_report (K report))))
+
 val add_generator = Data.map o apfst o AList.update (op =);
 
 (* generating tests *)
@@ -124,14 +133,14 @@
    of NONE => error ("No such quickcheck generator: " ^ name)
     | SOME generator => generator ctxt;
 
-fun mk_testers ctxt report t =
+fun mk_testers ctxt t =
   (map snd o fst o Data.get o Context.Proof) ctxt
-  |> map_filter (fn generator => try (generator ctxt report) t);
+  |> map_filter (fn generator => try (generator ctxt) t);
 
-fun mk_testers_strict ctxt report t =
+fun mk_testers_strict ctxt t =
   let
     val generators = ((map snd o fst o Data.get  o Context.Proof) ctxt)
-    val testers = map (fn generator => Exn.capture (generator ctxt report) t) generators;
+    val testers = map (fn generator => Exn.capture (generator ctxt) t) generators;
   in if forall (is_none o Exn.get_result) testers
     then [(Exn.release o snd o split_last) testers]
     else map_filter Exn.get_result testers
@@ -156,13 +165,13 @@
     val time = Time.toMilliseconds (#cpu (end_timing start))
   in (Exn.release result, (description, time)) end
 
-fun gen_test_term ctxt quiet report generator_name size i t =
+fun gen_test_term ctxt quiet generator_name size i t =
   let
     val (names, t') = prep_test_term t;
     val (testers, comp_time) = cpu_time "quickcheck compilation"
       (fn () => (case generator_name
-       of NONE => if quiet then mk_testers ctxt report t' else mk_testers_strict ctxt report t'
-        | SOME name => [mk_tester_select name ctxt report t']));
+       of NONE => if quiet then mk_testers ctxt t' else mk_testers_strict ctxt t'
+        | SOME name => [mk_tester_select name ctxt t']));
     fun iterate f 0 report = (NONE, report)
       | iterate f j report =
         let
@@ -190,11 +199,13 @@
          (fn result => case result of NONE => NONE
         | SOME ts => SOME (names ~~ ts)) (with_size 1 []))
   in
-    (result, ([exec_time, comp_time], if report then SOME reports else NONE))
+    (result, ([exec_time, comp_time], if report ctxt then SOME reports else NONE))
   end;
 
 fun test_term ctxt quiet generator_name size i t =
-  fst (gen_test_term ctxt quiet false generator_name size i t)
+  ctxt
+  |> set_reporting false
+  |> (fn ctxt' => fst (gen_test_term ctxt' quiet generator_name size i t))
 
 exception WELLSORTED of string
 
@@ -216,7 +227,7 @@
 
 datatype wellsorted_error = Wellsorted_Error of string | Term of term
 
-fun test_goal quiet report generator_name size iterations default_Ts no_assms insts i state =
+fun test_goal quiet generator_name size iterations default_Ts no_assms insts i state =
   let
     val lthy = Proof.context_of state;
     val thy = Proof.theory_of state;
@@ -249,7 +260,7 @@
         case f t of
           (SOME res, report) => (SOME res, rev (report :: reports))
         | (NONE, report) => collect_results f (report :: reports) ts
-  in collect_results (gen_test_term lthy quiet report generator_name size iterations) [] correct_inst_goals end;
+  in collect_results (gen_test_term lthy quiet generator_name size iterations) [] correct_inst_goals end;
 
 (* pretty printing *)
 
@@ -298,7 +309,9 @@
       val Test_Params {size, iterations, default_type, no_assms, ...} =
         (snd o Data.get o Context.Proof) ctxt;
       val res =
-        try (test_goal true false NONE size iterations default_type no_assms [] 1) state;
+        state
+        |> Proof.map_context (set_reporting false)
+        |> try (test_goal true NONE size iterations default_type no_assms [] 1);
     in
       case res of
         NONE => (false, state)
@@ -368,7 +381,9 @@
     val (((size, iterations), ((default_type, no_assms), ((expect, report), quiet))), (generator_name, insts)) =
       f (default_params, (NONE, []));
   in
-    test_goal quiet report generator_name size iterations default_type no_assms insts i state
+    state
+    |> Proof.map_context (set_reporting report)
+    |> test_goal quiet generator_name size iterations default_type no_assms insts i
     |> tap (fn (SOME x, _) => if expect = No_Counterexample then
                  error ("quickcheck expected to find no counterexample but found one") else ()
              | (NONE, _) => if expect = Counterexample then