84 |
84 |
85 exception FUNCTION_TYPE; |
85 exception FUNCTION_TYPE; |
86 |
86 |
87 exception Counterexample of term list |
87 exception Counterexample of term list |
88 |
88 |
|
89 val resultT = @{typ "(bool * term list) option"}; |
|
90 |
89 val exhaustiveN = "exhaustive"; |
91 val exhaustiveN = "exhaustive"; |
90 val full_exhaustiveN = "full_exhaustive"; |
92 val full_exhaustiveN = "full_exhaustive"; |
91 val fast_exhaustiveN = "fast_exhaustive"; |
93 val fast_exhaustiveN = "fast_exhaustive"; |
92 val bounded_forallN = "bounded_forall"; |
94 val bounded_forallN = "bounded_forall"; |
93 |
95 |
97 fun exhaustiveT T = (T --> @{typ "Code_Evaluation.term list option"}) |
99 fun exhaustiveT T = (T --> @{typ "Code_Evaluation.term list option"}) |
98 --> @{typ code_numeral} --> @{typ "Code_Evaluation.term list option"} |
100 --> @{typ code_numeral} --> @{typ "Code_Evaluation.term list option"} |
99 |
101 |
100 fun bounded_forallT T = (T --> @{typ bool}) --> @{typ code_numeral} --> @{typ bool} |
102 fun bounded_forallT T = (T --> @{typ bool}) --> @{typ code_numeral} --> @{typ bool} |
101 |
103 |
102 fun full_exhaustiveT T = (termifyT T --> @{typ "(bool * Code_Evaluation.term list) option"}) |
104 fun full_exhaustiveT T = (termifyT T --> resultT) --> @{typ code_numeral} --> resultT |
103 --> @{typ code_numeral} --> @{typ "(bool * Code_Evaluation.term list) option"} |
105 |
104 |
106 fun check_allT T = (termifyT T --> resultT) --> resultT |
105 fun check_allT T = (termifyT T --> @{typ "Code_Evaluation.term list option"}) |
|
106 --> @{typ "Code_Evaluation.term list option"} |
|
107 |
107 |
108 fun mk_equation_terms generics (descr, vs, Ts) = |
108 fun mk_equation_terms generics (descr, vs, Ts) = |
109 let |
109 let |
110 val (mk_call, mk_aux_call, mk_consexpr, mk_rhs, test_function, exhaustives) = generics |
110 val (mk_call, mk_aux_call, mk_consexpr, mk_rhs, test_function, exhaustives) = generics |
111 val rhss = |
111 val rhss = |
179 mk_equation_terms (mk_call, mk_aux_call, mk_consexpr, mk_rhs, test_function, functerms) |
179 mk_equation_terms (mk_call, mk_aux_call, mk_consexpr, mk_rhs, test_function, functerms) |
180 end |
180 end |
181 |
181 |
182 fun mk_full_equations functerms = |
182 fun mk_full_equations functerms = |
183 let |
183 let |
184 fun test_function T = Free ("f", termifyT T --> @{typ "(bool * term list) option"}) |
184 fun test_function T = Free ("f", termifyT T --> resultT) |
|
185 fun split_const T = HOLogic.split_const (T, @{typ "unit => Code_Evaluation.term"}, resultT) |
185 fun mk_call T = |
186 fun mk_call T = |
186 let |
187 let |
187 val full_exhaustive = |
188 val full_exhaustive = |
188 Const (@{const_name "Quickcheck_Exhaustive.full_exhaustive_class.full_exhaustive"}, |
189 Const (@{const_name "Quickcheck_Exhaustive.full_exhaustive_class.full_exhaustive"}, |
189 full_exhaustiveT T) |
190 full_exhaustiveT T) |
190 in |
191 in |
191 (T, fn t => full_exhaustive $ |
192 (T, fn t => full_exhaustive $ |
192 (HOLogic.split_const (T, @{typ "unit => Code_Evaluation.term"}, |
193 (split_const T $ absdummy T (absdummy @{typ "unit => Code_Evaluation.term"} t)) $ size_pred) |
193 @{typ "(bool * Code_Evaluation.term list) option"}) |
|
194 $ absdummy T (absdummy @{typ "unit => Code_Evaluation.term"} t)) $ size_pred) |
|
195 end |
194 end |
196 fun mk_aux_call fTs (k, _) (tyco, Ts) = |
195 fun mk_aux_call fTs (k, _) (tyco, Ts) = |
197 let |
196 let |
198 val T = Type (tyco, Ts) |
197 val T = Type (tyco, Ts) |
199 val _ = if not (null fTs) then raise FUNCTION_TYPE else () |
198 val _ = if not (null fTs) then raise FUNCTION_TYPE else () |
200 in |
199 in |
201 (T, fn t => nth functerms k $ |
200 (T, fn t => nth functerms k $ |
202 (HOLogic.split_const (T, @{typ "unit => Code_Evaluation.term"}, |
201 (split_const T $ absdummy T (absdummy @{typ "unit => Code_Evaluation.term"} t)) $ size_pred) |
203 @{typ "(bool * Code_Evaluation.term list) option"}) |
|
204 $ absdummy T (absdummy @{typ "unit => Code_Evaluation.term"} t)) $ size_pred) |
|
205 end |
202 end |
206 fun mk_consexpr simpleT (c, xs) = |
203 fun mk_consexpr simpleT (c, xs) = |
207 let |
204 let |
208 val (Ts, fns) = split_list xs |
205 val (Ts, fns) = split_list xs |
209 val constr = Const (c, Ts ---> simpleT) |
206 val constr = Const (c, Ts ---> simpleT) |
217 (HOLogic.pair_const simpleT @{typ "unit => Code_Evaluation.term"} |
214 (HOLogic.pair_const simpleT @{typ "unit => Code_Evaluation.term"} |
218 $ (list_comb (constr, bounds)) $ absdummy @{typ unit} term) |
215 $ (list_comb (constr, bounds)) $ absdummy @{typ unit} term) |
219 in fold_rev (fn f => fn t => f t) fns start_term end |
216 in fold_rev (fn f => fn t => f t) fns start_term end |
220 fun mk_rhs exprs = |
217 fun mk_rhs exprs = |
221 mk_if (size_ge_zero, foldr1 mk_none_continuation exprs, |
218 mk_if (size_ge_zero, foldr1 mk_none_continuation exprs, |
222 @{term "None :: (bool * term list) option"}) |
219 Const (@{const_name "None"}, resultT)) |
223 in |
220 in |
224 mk_equation_terms (mk_call, mk_aux_call, mk_consexpr, mk_rhs, test_function, functerms) |
221 mk_equation_terms (mk_call, mk_aux_call, mk_consexpr, mk_rhs, test_function, functerms) |
225 end |
222 end |
226 |
223 |
227 (** foundational definition with the function package **) |
224 (** foundational definition with the function package **) |
371 (HOLogic.mk_list @{typ term} |
368 (HOLogic.mk_list @{typ term} |
372 (map (fn v => v $ @{term "()"}) term_vars @ map mk_safe_term eval_terms))) |
369 (map (fn v => v $ @{term "()"}) term_vars @ map mk_safe_term eval_terms))) |
373 fun mk_exhaustive_closure (free as Free (_, T), term_var) t = |
370 fun mk_exhaustive_closure (free as Free (_, T), term_var) t = |
374 if Sign.of_sort thy (T, @{sort enum}) then |
371 if Sign.of_sort thy (T, @{sort enum}) then |
375 Const (@{const_name "Quickcheck_Exhaustive.check_all_class.check_all"}, check_allT T) |
372 Const (@{const_name "Quickcheck_Exhaustive.check_all_class.check_all"}, check_allT T) |
376 $ (HOLogic.split_const (T, @{typ "unit => term"}, @{typ "term list option"}) |
373 $ (HOLogic.split_const (T, @{typ "unit => term"}, resultT) |
377 $ lambda free (lambda term_var t)) |
374 $ lambda free (lambda term_var t)) |
378 else |
375 else |
379 Const (@{const_name "Quickcheck_Exhaustive.full_exhaustive_class.full_exhaustive"}, full_exhaustiveT T) |
376 Const (@{const_name "Quickcheck_Exhaustive.full_exhaustive_class.full_exhaustive"}, full_exhaustiveT T) |
380 $ (HOLogic.split_const (T, @{typ "unit => term"}, @{typ "(bool * term list) option"}) |
377 $ (HOLogic.split_const (T, @{typ "unit => term"}, resultT) |
381 $ lambda free (lambda term_var t)) $ depth |
378 $ lambda free (lambda term_var t)) $ depth |
382 val none_t = @{term "None :: (bool * term list) option"} |
379 val none_t = Const (@{const_name "None"}, resultT) |
383 val mk_if = Quickcheck_Common.mk_safe_if ctxt |
380 val mk_if = Quickcheck_Common.mk_safe_if ctxt |
384 val mk_test_term = mk_test_term lookup mk_exhaustive_closure mk_if none_t return ctxt |
381 val mk_test_term = mk_test_term lookup mk_exhaustive_closure mk_if none_t return ctxt |
385 in lambda depth (mk_test_term t) end |
382 in lambda depth (mk_test_term t) end |
386 |
383 |
387 fun mk_parametric_generator_expr mk_generator_expr = |
384 fun mk_parametric_generator_expr mk_generator_expr = |
388 Quickcheck_Common.gen_mk_parametric_generator_expr |
385 Quickcheck_Common.gen_mk_parametric_generator_expr |
389 ((mk_generator_expr, absdummy @{typ "code_numeral"} @{term "None :: (bool * term list) option"}), |
386 ((mk_generator_expr, absdummy @{typ "code_numeral"} (Const (@{const_name "None"}, resultT))), |
390 @{typ "code_numeral => (bool * term list) option"}) |
387 @{typ "code_numeral"} --> resultT) |
391 |
388 |
392 fun mk_validator_expr ctxt t = |
389 fun mk_validator_expr ctxt t = |
393 let |
390 let |
394 fun bounded_forallT T = (T --> @{typ bool}) --> @{typ code_numeral} --> @{typ bool} |
391 fun bounded_forallT T = (T --> @{typ bool}) --> @{typ code_numeral} --> @{typ bool} |
395 val thy = Proof_Context.theory_of ctxt |
392 val thy = Proof_Context.theory_of ctxt |