src/HOL/Tools/Quickcheck/quickcheck_common.ML
changeset 46331 f5598b604a54
parent 46327 ecda23528833
child 46478 cf1bcfb34c82
equal deleted inserted replaced
46330:2ddc00f8ad7c 46331:f5598b604a54
    14     -> (string * sort -> string * sort) option
    14     -> (string * sort -> string * sort) option
    15   val instantiate_goals: Proof.context -> (string * typ) list -> (term * term list) list
    15   val instantiate_goals: Proof.context -> (string * typ) list -> (term * term list) list
    16     -> (typ option * (term * term list)) list list
    16     -> (typ option * (term * term list)) list list
    17   val mk_safe_if : term -> term -> term * term * (bool -> term) -> bool -> term
    17   val mk_safe_if : term -> term -> term * term * (bool -> term) -> bool -> term
    18   val collect_results : ('a -> Quickcheck.result) -> 'a list -> Quickcheck.result list -> Quickcheck.result list
    18   val collect_results : ('a -> Quickcheck.result) -> 'a list -> Quickcheck.result list -> Quickcheck.result list
    19   type compile_generator =
    19   type result = (bool * term list) option * Quickcheck.report option
    20     Proof.context -> (term * term list) list -> bool -> int list -> (bool * term list) option * Quickcheck.report option
    20   type generator = string * ((theory -> typ list -> bool) * 
       
    21       (Proof.context -> (term * term list) list -> bool -> int list -> result))
    21   val generator_test_goal_terms :
    22   val generator_test_goal_terms :
    22     string * compile_generator -> Proof.context -> bool -> (string * typ) list
    23     generator -> Proof.context -> bool -> (string * typ) list
    23     -> (term * term list) list -> Quickcheck.result list
    24       -> (term * term list) list -> Quickcheck.result list
    24   type instantiation = Datatype.config -> Datatype.descr -> (string * sort) list
    25   type instantiation = Datatype.config -> Datatype.descr -> (string * sort) list
    25      -> string list -> string -> string list * string list -> typ list * typ list -> theory -> theory
    26      -> string list -> string -> string list * string list -> typ list * typ list -> theory -> theory
    26   val ensure_sort :
    27   val ensure_sort :
    27     (((sort * sort) * sort) *
    28     (((sort * sort) * sort) *
    28       ((theory -> string list -> Datatype_Aux.descr * (string * sort) list * string list
    29       ((theory -> string list -> Datatype_Aux.descr * (string * sort) list * string list
    34   val gen_mk_parametric_generator_expr :
    35   val gen_mk_parametric_generator_expr :
    35    (((Proof.context -> term * term list -> term) * term) * typ)
    36    (((Proof.context -> term * term list -> term) * term) * typ)
    36      -> Proof.context -> (term * term list) list -> term
    37      -> Proof.context -> (term * term list) list -> term
    37   val mk_fun_upd : typ -> typ -> term * term -> term -> term
    38   val mk_fun_upd : typ -> typ -> term * term -> term -> term
    38   val post_process_term : term -> term
    39   val post_process_term : term -> term
    39   val test_term : string * compile_generator
    40   val test_term : generator -> Proof.context -> bool -> term * term list -> Quickcheck.result
    40     -> Proof.context -> bool -> term * term list -> Quickcheck.result
       
    41 end;
    41 end;
    42 
    42 
    43 structure Quickcheck_Common : QUICKCHECK_COMMON =
    43 structure Quickcheck_Common : QUICKCHECK_COMMON =
    44 struct
    44 struct
    45 
    45 
    56 
    56 
    57 fun mk_undefined T = Const(@{const_name undefined}, T)
    57 fun mk_undefined T = Const(@{const_name undefined}, T)
    58 
    58 
    59 (* testing functions: testing with increasing sizes (and cardinalities) *)
    59 (* testing functions: testing with increasing sizes (and cardinalities) *)
    60 
    60 
    61 type compile_generator =
    61 type result = (bool * term list) option * Quickcheck.report option
    62   Proof.context -> (term * term list) list -> bool -> int list -> (bool * term list) option * Quickcheck.report option
    62 type generator = string * ((theory -> typ list -> bool) * 
       
    63       (Proof.context -> (term * term list) list -> bool -> int list -> result))
    63 
    64 
    64 fun check_test_term t =
    65 fun check_test_term t =
    65   let
    66   let
    66     val _ = (null (Term.add_tvars t []) andalso null (Term.add_tfrees t [])) orelse
    67     val _ = (null (Term.add_tvars t []) andalso null (Term.add_tfrees t [])) orelse
    67       error "Term to be tested contains type variables";
    68       error "Term to be tested contains type variables";
    71 
    72 
    72 fun cpu_time description e =
    73 fun cpu_time description e =
    73   let val ({cpu, ...}, result) = Timing.timing e ()
    74   let val ({cpu, ...}, result) = Timing.timing e ()
    74   in (result, (description, Time.toMilliseconds cpu)) end
    75   in (result, (description, Time.toMilliseconds cpu)) end
    75 
    76 
    76 fun test_term (name, compile) ctxt catch_code_errors (t, eval_terms) =
    77 fun test_term (name, (_, compile)) ctxt catch_code_errors (t, eval_terms) =
    77   let
    78   let
    78     val genuine_only = Config.get ctxt Quickcheck.genuine_only
    79     val genuine_only = Config.get ctxt Quickcheck.genuine_only
    79     val _ = check_test_term t
    80     val _ = check_test_term t
    80     val names = Term.add_free_names t []
    81     val names = Term.add_free_names t []
    81     val current_size = Unsynchronized.ref 0
    82     val current_size = Unsynchronized.ref 0
   163   in
   164   in
   164     (Option.map (map2 (fn names => Option.map (fn ts => names ~~ ts)) namess) results,
   165     (Option.map (map2 (fn names => Option.map (fn ts => names ~~ ts)) namess) results,
   165       [comp_time, exec_time])
   166       [comp_time, exec_time])
   166   end
   167   end
   167 
   168 
   168 fun test_term_with_cardinality (name, compile) ctxt catch_code_errors ts =
   169 fun test_term_with_cardinality (name, (size_matters_for, compile)) ctxt catch_code_errors ts =
   169   let
   170   let
   170     val genuine_only = Config.get ctxt Quickcheck.genuine_only
   171     val genuine_only = Config.get ctxt Quickcheck.genuine_only
   171     val thy = Proof_Context.theory_of ctxt
   172     val thy = Proof_Context.theory_of ctxt
   172     val (ts', eval_terms) = split_list ts
   173     val (ts', eval_terms) = split_list ts
   173     val _ = map check_test_term ts'
   174     val _ = map check_test_term ts'
   187         val _ = Quickcheck.add_timing timing current_result
   188         val _ = Quickcheck.add_timing timing current_result
   188       in
   189       in
   189         Option.map (pair (card, size)) ts
   190         Option.map (pair (card, size)) ts
   190       end
   191       end
   191     val enumeration_card_size =
   192     val enumeration_card_size =
   192       if forall (fn T => Sign.of_sort thy (T,  ["Enum.enum"])) Ts then
   193       if size_matters_for thy Ts then
   193         (* size does not matter *)
       
   194         map (rpair 0) (1 upto (length ts))
       
   195       else
       
   196         (* size does matter *)
       
   197         map_product pair (1 upto (length ts)) (1 upto (Config.get ctxt Quickcheck.size))
   194         map_product pair (1 upto (length ts)) (1 upto (Config.get ctxt Quickcheck.size))
   198         |> sort (fn ((c1, s1), (c2, s2)) => int_ord ((c1 + s1), (c2 + s2)))
   195         |> sort (fn ((c1, s1), (c2, s2)) => int_ord ((c1 + s1), (c2 + s2)))
       
   196       else
       
   197         map (rpair 0) (1 upto (length ts))
   199     val act = if catch_code_errors then try else (fn f => SOME o f)
   198     val act = if catch_code_errors then try else (fn f => SOME o f)
   200     val (test_fun, comp_time) = cpu_time "quickcheck compilation" (fn () => act (compile ctxt) ts)
   199     val (test_fun, comp_time) = cpu_time "quickcheck compilation" (fn () => act (compile ctxt) ts)
   201     val _ = Quickcheck.add_timing comp_time current_result
   200     val _ = Quickcheck.add_timing comp_time current_result
   202   in
   201   in
   203     case test_fun of
   202     case test_fun of
   323         (result :: results)
   322         (result :: results)
   324       else
   323       else
   325         collect_results f ts (result :: results)
   324         collect_results f ts (result :: results)
   326     end  
   325     end  
   327 
   326 
   328 fun generator_test_goal_terms (name, compile) ctxt catch_code_errors insts goals =
   327 fun generator_test_goal_terms generator ctxt catch_code_errors insts goals =
   329   let
   328   let
   330     fun add_eval_term t ts = if is_Free t then ts else ts @ [t]
   329     fun add_eval_term t ts = if is_Free t then ts else ts @ [t]
   331     fun add_equation_eval_terms (t, eval_terms) =
   330     fun add_equation_eval_terms (t, eval_terms) =
   332       case try HOLogic.dest_eq (snd (strip_imp t)) of
   331       case try HOLogic.dest_eq (snd (strip_imp t)) of
   333         SOME (lhs, rhs) => (t, add_eval_term lhs (add_eval_term rhs eval_terms))
   332         SOME (lhs, rhs) => (t, add_eval_term lhs (add_eval_term rhs eval_terms))
   334       | NONE => (t, eval_terms)
   333       | NONE => (t, eval_terms)
   335     fun test_term' goal =
   334     fun test_term' goal =
   336       case goal of
   335       case goal of
   337         [(NONE, t)] => test_term (name, compile) ctxt catch_code_errors t
   336         [(NONE, t)] => test_term generator ctxt catch_code_errors t
   338       | ts => test_term_with_cardinality (name, compile) ctxt catch_code_errors (map snd ts)
   337       | ts => test_term_with_cardinality generator ctxt catch_code_errors (map snd ts)
   339     val goals' = instantiate_goals ctxt insts goals
   338     val goals' = instantiate_goals ctxt insts goals
   340       |> map (map (apsnd add_equation_eval_terms))
   339       |> map (map (apsnd add_equation_eval_terms))
   341   in
   340   in
   342     if Config.get ctxt Quickcheck.finite_types then
   341     if Config.get ctxt Quickcheck.finite_types then
   343       collect_results test_term' goals' []
   342       collect_results test_term' goals' []
   344     else
   343     else
   345       collect_results (test_term (name, compile) ctxt catch_code_errors)
   344       collect_results (test_term generator ctxt catch_code_errors)
   346         (maps (map snd) goals') []
   345         (maps (map snd) goals') []
   347   end;
   346   end;
   348 
   347 
   349 (* defining functions *)
   348 (* defining functions *)
   350 
   349