49017
|
1 |
(* Title: HOL/Codatatype/Tools/bnf_sugar.ML
|
|
2 |
Author: Jasmin Blanchette, TU Muenchen
|
|
3 |
Copyright 2012
|
|
4 |
|
|
5 |
Sugar on top of a BNF.
|
|
6 |
*)
|
|
7 |
|
|
8 |
signature BNF_SUGAR =
|
|
9 |
sig
|
|
10 |
end;
|
|
11 |
|
|
12 |
structure BNF_Sugar : BNF_SUGAR =
|
|
13 |
struct
|
|
14 |
|
|
15 |
open BNF_Util
|
49019
|
16 |
open BNF_FP_Util
|
49017
|
17 |
|
49019
|
18 |
val distinctN = "distinct";
|
|
19 |
|
|
20 |
fun prepare_sugar prep_typ prep_term ((((raw_T, raw_ctors), raw_dtors), raw_storss), raw_recur)
|
|
21 |
lthy =
|
49017
|
22 |
let
|
49019
|
23 |
(* TODO: sanity checks on arguments *)
|
49017
|
24 |
|
49019
|
25 |
val T as Type (T_name, _) = prep_typ lthy raw_T;
|
|
26 |
val b = Binding.qualified_name T_name;
|
|
27 |
|
|
28 |
val ctors = map (prep_term lthy) raw_ctors;
|
49017
|
29 |
val ctor_Tss = map (binder_types o fastype_of) ctors;
|
|
30 |
|
49019
|
31 |
val ((xss, yss), _) = lthy |>
|
|
32 |
mk_Freess "x" ctor_Tss
|
|
33 |
||>> mk_Freess "y" ctor_Tss;
|
|
34 |
|
|
35 |
val goal_injects =
|
49017
|
36 |
let
|
49019
|
37 |
fun mk_goal _ [] [] = NONE
|
|
38 |
| mk_goal ctor xs ys =
|
|
39 |
SOME (HOLogic.mk_Trueprop (HOLogic.mk_eq
|
|
40 |
(HOLogic.mk_eq (Term.list_comb (ctor, xs), Term.list_comb (ctor, ys)),
|
|
41 |
Library.foldr1 HOLogic.mk_conj (map2 (curry HOLogic.mk_eq) xs ys))));
|
49017
|
42 |
in
|
49019
|
43 |
map_filter I (map3 mk_goal ctors xss yss)
|
49017
|
44 |
end;
|
|
45 |
|
49019
|
46 |
val goal_half_distincts =
|
|
47 |
let
|
|
48 |
fun mk_goal t u = HOLogic.mk_Trueprop (HOLogic.mk_not (HOLogic.mk_eq (t, u)));
|
|
49 |
fun mk_goals [] = []
|
|
50 |
| mk_goals (t :: ts) = fold_rev (cons o mk_goal t) ts (mk_goals ts);
|
|
51 |
in
|
|
52 |
mk_goals (map2 (curry Term.list_comb) ctors xss)
|
|
53 |
end;
|
|
54 |
|
|
55 |
val goals = [goal_injects, goal_half_distincts];
|
|
56 |
|
|
57 |
fun after_qed thmss lthy =
|
|
58 |
let
|
|
59 |
val [inject_thms, half_distinct_thms] = thmss;
|
|
60 |
|
|
61 |
val other_half_distinct_thms = map (fn thm => thm RS not_sym) half_distinct_thms;
|
|
62 |
|
|
63 |
fun note thmN thms =
|
|
64 |
snd o Local_Theory.note
|
|
65 |
((Binding.qualify true (Binding.name_of b) (Binding.name thmN), []), thms);
|
|
66 |
in
|
|
67 |
lthy
|
|
68 |
|> note injectN inject_thms
|
|
69 |
|> note distinctN (half_distinct_thms @ other_half_distinct_thms)
|
|
70 |
end;
|
49017
|
71 |
in
|
49019
|
72 |
(goals, after_qed, lthy)
|
49017
|
73 |
end;
|
|
74 |
|
|
75 |
val parse_binding_list = Parse.$$$ "[" |-- Parse.list Parse.binding --| Parse.$$$ "]";
|
|
76 |
|
49019
|
77 |
val bnf_sugar_cmd = (fn (goalss, after_qed, lthy) =>
|
|
78 |
Proof.theorem NONE after_qed (map (map (rpair [])) goalss) lthy) oo
|
|
79 |
prepare_sugar Syntax.read_typ Syntax.read_term;
|
49017
|
80 |
|
|
81 |
val _ =
|
|
82 |
Outer_Syntax.local_theory_to_proof @{command_spec "bnf_sugar"} "adds sugar on top of a BNF"
|
|
83 |
((Parse.typ -- (Parse.$$$ "[" |-- Parse.list Parse.term --| Parse.$$$ "]") --
|
|
84 |
parse_binding_list -- (Parse.$$$ "[" |-- Parse.list parse_binding_list --| Parse.$$$ "]") --
|
|
85 |
Parse.term) >> bnf_sugar_cmd);
|
|
86 |
|
|
87 |
end;
|