src/HOL/Tools/Quickcheck/exhaustive_generators.ML
changeset 45722 63b42a7db003
parent 45721 d1fb55c2ed65
child 45724 1f5fc44254d7
equal deleted inserted replaced
45721:d1fb55c2ed65 45722:63b42a7db003
    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