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 |