| author | nipkow | 
| Mon, 10 Sep 2018 15:08:56 +0200 | |
| changeset 68966 | 2881f6cccc67 | 
| parent 67149 | e61557884799 | 
| child 80634 | a90ab1ea6458 | 
| permissions | -rw-r--r-- | 
| 45925 | 1 | (* Title: HOL/Tools/Quickcheck/abstract_generators.ML | 
| 2 | Author: Lukas Bulwahn, TU Muenchen | |
| 3 | ||
| 4 | Quickcheck generators for abstract types. | |
| 5 | *) | |
| 6 | ||
| 7 | signature ABSTRACT_GENERATORS = | |
| 8 | sig | |
| 46564 
daa915508f63
adding parsing of an optional predicate with quickcheck_generator command
 bulwahn parents: 
45940diff
changeset | 9 | val quickcheck_generator : string -> term option -> term list -> theory -> theory | 
| 62979 | 10 | end | 
| 45925 | 11 | |
| 12 | structure Abstract_Generators : ABSTRACT_GENERATORS = | |
| 13 | struct | |
| 14 | ||
| 15 | fun check_constrs ctxt tyco constrs = | |
| 16 | let | |
| 17 | fun check_type c = | |
| 62979 | 18 | (case try (dest_Type o body_type o fastype_of) c of | 
| 45925 | 19 | NONE => error (Syntax.string_of_term ctxt c ^ " has mismatching result type.") | 
| 20 | | SOME (tyco', vs) => if not (tyco' = tyco) then | |
| 21 | error (Syntax.string_of_term ctxt c ^ " has mismatching result type. " ^ | |
| 22 | "Expected type constructor " ^ quote tyco ^ ", but found " ^ quote tyco' ^ ".") | |
| 23 | else | |
| 62979 | 24 | (case try (map dest_TFree) vs of | 
| 45925 | 25 | NONE => error (Syntax.string_of_term ctxt c ^ " has mismatching result type.") | 
| 62979 | 26 | | SOME _ => ())) | 
| 27 | in map check_type constrs end | |
| 28 | ||
| 46564 
daa915508f63
adding parsing of an optional predicate with quickcheck_generator command
 bulwahn parents: 
45940diff
changeset | 29 | fun gen_quickcheck_generator prep_tyco prep_term tyco_raw opt_pred_raw constrs_raw thy = | 
| 45925 | 30 | let | 
| 31 | val ctxt = Proof_Context.init_global thy | |
| 32 | val tyco = prep_tyco ctxt tyco_raw | |
| 46565 | 33 | val opt_pred = Option.map (prep_term ctxt) opt_pred_raw | 
| 45925 | 34 | val constrs = map (prep_term ctxt) constrs_raw | 
| 46565 | 35 | val _ = check_constrs ctxt tyco constrs | 
| 45925 | 36 | val vs = map dest_TFree (snd (dest_Type (body_type (fastype_of (hd constrs))))) | 
| 62979 | 37 | val name = Long_Name.base_name tyco | 
| 45925 | 38 | fun mk_dconstrs (Const (s, T)) = | 
| 62979 | 39 | (s, map (Old_Datatype_Aux.dtyp_of_typ [(tyco, vs)]) (binder_types T)) | 
| 40 | | mk_dconstrs t = | |
| 41 | error (Syntax.string_of_term ctxt t ^ | |
| 42 | " is not a valid constructor for quickcheck_generator, which expects a constant.") | |
| 46564 
daa915508f63
adding parsing of an optional predicate with quickcheck_generator command
 bulwahn parents: 
45940diff
changeset | 43 | fun the_descr _ _ = | 
| 62979 | 44 | let val descr = [(0, (tyco, map Old_Datatype_Aux.DtTFree vs, map mk_dconstrs constrs))] | 
| 45 | in (descr, vs, [tyco], name, ([name], []), ([Type (tyco, map TFree vs)], [])) end | |
| 45940 
71970a26a269
quickcheck_generator command also creates random generators
 bulwahn parents: 
45925diff
changeset | 46 | fun ensure_sort (sort, instantiate) = | 
| 62979 | 47 | Quickcheck_Common.ensure_sort | 
| 67149 | 48 | (((\<^sort>\<open>typerep\<close>, \<^sort>\<open>term_of\<close>), sort), (the_descr, instantiate)) | 
| 62979 | 49 | Old_Datatype_Aux.default_config [tyco] | 
| 45925 | 50 | in | 
| 45940 
71970a26a269
quickcheck_generator command also creates random generators
 bulwahn parents: 
45925diff
changeset | 51 | thy | 
| 62979 | 52 | |> ensure_sort | 
| 67149 | 53 | (\<^sort>\<open>full_exhaustive\<close>, Exhaustive_Generators.instantiate_full_exhaustive_datatype) | 
| 54 | |> ensure_sort (\<^sort>\<open>exhaustive\<close>, Exhaustive_Generators.instantiate_exhaustive_datatype) | |
| 55 | |> ensure_sort (\<^sort>\<open>random\<close>, Random_Generators.instantiate_random_datatype) | |
| 62979 | 56 | |> (case opt_pred of NONE => I | 
| 57 | | SOME t => Context.theory_map (Quickcheck_Common.register_predicate (t, tyco))) | |
| 45925 | 58 | end | 
| 59 | ||
| 60 | val quickcheck_generator = gen_quickcheck_generator (K I) (K I) | |
| 62979 | 61 | |
| 55951 
c07d184aebe9
tuned signature -- more uniform check_type_name/read_type_name;
 wenzelm parents: 
46961diff
changeset | 62 | val quickcheck_generator_cmd = | 
| 
c07d184aebe9
tuned signature -- more uniform check_type_name/read_type_name;
 wenzelm parents: 
46961diff
changeset | 63 | gen_quickcheck_generator | 
| 56002 | 64 |     ((#1 o dest_Type) oo Proof_Context.read_type_name {proper = true, strict = true})
 | 
| 55951 
c07d184aebe9
tuned signature -- more uniform check_type_name/read_type_name;
 wenzelm parents: 
46961diff
changeset | 65 | Syntax.read_term | 
| 62979 | 66 | |
| 46961 
5c6955f487e5
outer syntax command definitions based on formal command_spec derived from theory header declarations;
 wenzelm parents: 
46949diff
changeset | 67 | val _ = | 
| 67149 | 68 | Outer_Syntax.command \<^command_keyword>\<open>quickcheck_generator\<close> | 
| 46961 
5c6955f487e5
outer syntax command definitions based on formal command_spec derived from theory header declarations;
 wenzelm parents: 
46949diff
changeset | 69 | "define quickcheck generators for abstract types" | 
| 
5c6955f487e5
outer syntax command definitions based on formal command_spec derived from theory header declarations;
 wenzelm parents: 
46949diff
changeset | 70 | ((Parse.type_const -- | 
| 67149 | 71 | Scan.option (Args.$$$ "predicate" |-- \<^keyword>\<open>:\<close> |-- Parse.term)) -- | 
| 72 | (Args.$$$ "constructors" |-- \<^keyword>\<open>:\<close> |-- Parse.list1 Parse.term) | |
| 46564 
daa915508f63
adding parsing of an optional predicate with quickcheck_generator command
 bulwahn parents: 
45940diff
changeset | 73 | >> (fn ((tyco, opt_pred), constrs) => | 
| 
daa915508f63
adding parsing of an optional predicate with quickcheck_generator command
 bulwahn parents: 
45940diff
changeset | 74 | Toplevel.theory (quickcheck_generator_cmd tyco opt_pred constrs))) | 
| 45925 | 75 | |
| 62979 | 76 | end |