1 (* Title: HOL/Tools/Predicate_Compile/predicate_compile_data.ML
2 Author: Lukas Bulwahn, TU Muenchen
4 Book-keeping datastructure for the predicate compiler.
7 signature PREDICATE_COMPILE_DATA =
9 val ignore_consts : string list -> theory -> theory
10 val keep_functions : string list -> theory -> theory
11 val keep_function : theory -> string -> bool
12 val processed_specs : theory -> string -> (string * thm list) list option
13 val store_processed_specs : (string * (string * thm list) list) -> theory -> theory
15 val get_specification : Predicate_Compile_Aux.options -> theory -> term -> thm list
16 val obtain_specification_graph :
17 Predicate_Compile_Aux.options -> theory -> term -> thm list Term_Graph.T
19 val present_graph : thm list Term_Graph.T -> unit
20 val normalize_equation : theory -> thm -> thm
23 structure Predicate_Compile_Data : PREDICATE_COMPILE_DATA =
26 open Predicate_Compile_Aux;
28 structure Data = Theory_Data
31 {ignore_consts : unit Symtab.table,
32 keep_functions : unit Symtab.table,
33 processed_specs : ((string * thm list) list) Symtab.table};
35 {ignore_consts = Symtab.empty,
36 keep_functions = Symtab.empty,
37 processed_specs = Symtab.empty};
40 ({ignore_consts = c1, keep_functions = k1, processed_specs = s1},
41 {ignore_consts = c2, keep_functions = k2, processed_specs = s2}) =
42 {ignore_consts = Symtab.merge (K true) (c1, c2),
43 keep_functions = Symtab.merge (K true) (k1, k2),
44 processed_specs = Symtab.merge (K true) (s1, s2)}
49 fun mk_data (c, k, s) = {ignore_consts = c, keep_functions = k, processed_specs = s}
50 fun map_data f {ignore_consts = c, keep_functions = k, processed_specs = s} = mk_data (f (c, k, s))
52 fun ignore_consts cs = Data.map (map_data (apfst3 (fold (fn c => Symtab.insert (op =) (c, ())) cs)))
54 fun keep_functions cs = Data.map (map_data (apsnd3 (fold (fn c => Symtab.insert (op =) (c, ())) cs)))
56 fun keep_function thy = Symtab.defined (#keep_functions (Data.get thy))
58 fun processed_specs thy = Symtab.lookup (#processed_specs (Data.get thy))
60 fun store_processed_specs (constname, specs) =
61 Data.map (map_data (aptrd3 (Symtab.update_new (constname, specs))))
65 fun defining_term_of_introrule_term t =
67 val _ $ u = Logic.strip_imp_concl t
68 in fst (strip_comb u) end
72 | _ => raise TERM ("defining_const_of_introrule_term failed: Not a constant", [t])
75 val defining_term_of_introrule = defining_term_of_introrule_term o prop_of
78 fun is_introlike_term t = true
80 val is_introlike = is_introlike_term o prop_of
82 fun check_equation_format_term (t as (Const ("==", _) $ u $ v)) =
84 (Const (c, T), args) =>
85 if (length (binder_types T) = length args) then
88 raise TERM ("check_equation_format_term failed: Number of arguments mismatch", [t])
89 | _ => raise TERM ("check_equation_format_term failed: Not a constant", [t]))
90 | check_equation_format_term t =
91 raise TERM ("check_equation_format_term failed: Not an equation", [t])
93 val check_equation_format = check_equation_format_term o prop_of
96 fun defining_term_of_equation_term (t as (Const ("==", _) $ u $ v)) = fst (strip_comb u)
97 | defining_term_of_equation_term t =
98 raise TERM ("defining_const_of_equation_term failed: Not an equation", [t])
100 val defining_term_of_equation = defining_term_of_equation_term o prop_of
102 fun defining_const_of_equation th =
103 case defining_term_of_equation th
105 | _ => raise TERM ("defining_const_of_equation failed: Not a constant", [prop_of th])
110 (* Normalizing equations *)
112 fun mk_meta_equation th =
114 Const ("Trueprop", _) $ (Const ("op =", _) $ _ $ _) => th RS @{thm eq_reflection}
117 val meta_fun_cong = @{lemma "f == g ==> f x == g x" by simp}
119 fun full_fun_cong_expand th =
121 val (f, args) = strip_comb (fst (Logic.dest_equals (prop_of th)))
122 val i = length (binder_types (fastype_of f)) - length args
123 in funpow i (fn th => th RS meta_fun_cong) th end;
125 fun declare_names s xs ctxt =
127 val res = Name.names ctxt s xs
128 in (res, fold Name.declare (map fst res) ctxt) end
130 fun split_all_pairs thy th =
132 val ctxt = ProofContext.init_global thy
133 val ((_, [th']), ctxt') = Variable.import true [th] ctxt
135 val frees = Term.add_frees t []
136 val freenames = Term.add_free_names t []
137 val nctxt = Name.make_context freenames
138 fun mk_tuple_rewrites (x, T) nctxt =
140 val Ts = HOLogic.flatten_tupleT T
141 val (xTs, nctxt') = declare_names x Ts nctxt
142 val paths = HOLogic.flat_tupleT_paths T
143 in ((Free (x, T), HOLogic.mk_ptuple paths T (map Free xTs)), nctxt') end
144 val (rewr, _) = fold_map mk_tuple_rewrites frees nctxt
145 val t' = Pattern.rewrite_term thy rewr [] t
146 val tac = Skip_Proof.cheat_tac thy
147 val th'' = Goal.prove ctxt (Term.add_free_names t' []) [] t' (fn _ => tac)
148 val th''' = Local_Defs.unfold ctxt [@{thm split_conv}, @{thm fst_conv}, @{thm snd_conv}] th''
154 fun inline_equations thy th =
156 val inline_defs = Predicate_Compile_Inline_Defs.get (ProofContext.init_global thy)
157 val th' = (Simplifier.full_simplify (HOL_basic_ss addsimps inline_defs)) th
158 (*val _ = print_step options
159 ("Inlining " ^ (Syntax.string_of_term_global thy (prop_of th))
160 ^ "with " ^ (commas (map ((Syntax.string_of_term_global thy) o prop_of) inline_defs))
161 ^" to " ^ (Syntax.string_of_term_global thy (prop_of th')))*)
166 fun normalize_equation thy th =
168 |> full_fun_cong_expand
169 |> split_all_pairs thy
170 |> tap check_equation_format
171 |> inline_equations thy
173 fun normalize_intros thy th =
174 split_all_pairs thy th
175 |> inline_equations thy
177 fun normalize thy th =
178 if is_equationlike th then
179 normalize_equation thy th
181 normalize_intros thy th
183 fun get_specification options thy t =
185 (*val (c, T) = dest_Const t
186 val t = Const (AxClass.unoverload_const thy (c, T), T)*)
187 val _ = if show_steps options then
188 tracing ("getting specification of " ^ Syntax.string_of_term_global thy t ^
189 " with type " ^ Syntax.string_of_typ_global thy (fastype_of t))
191 val ctxt = ProofContext.init_global thy
193 if is_equationlike th andalso
194 defining_const_of_equation (normalize_equation thy th) = fst (dest_Const t) then
195 SOME (normalize_equation thy th)
197 if is_introlike th andalso defining_term_of_introrule th = t then
201 fun filter_defs ths = map_filter filtering (map (normalize thy o Thm.transfer thy) ths)
202 val spec = case filter_defs (Predicate_Compile_Alternative_Defs.get ctxt) of
203 [] => (case Spec_Rules.retrieve ctxt t of
204 [] => error ("No specification for " ^ (Syntax.string_of_term_global thy t))
205 | ((_, (_, ths)) :: _) => filter_defs ths)
208 if show_intermediate_results options then
209 Output.tracing (commas (map (Display.string_of_thm_global thy) spec))
215 val logic_operator_names =
218 @{const_name "Trueprop"},
220 @{const_name "op ="},
221 @{const_name "op -->"},
224 @{const_name "op &"},
225 @{const_name "op |"}]
227 fun special_cases (c, T) = member (op =) [
228 @{const_name Product_Type.Unity},
230 @{const_name Suc}, @{const_name Nat.zero_nat_inst.zero_nat},
231 @{const_name Nat.one_nat_inst.one_nat},
232 @{const_name Orderings.less}, @{const_name Orderings.less_eq},
233 @{const_name Groups.zero},
234 @{const_name Groups.one}, @{const_name Groups.plus},
235 @{const_name Nat.ord_nat_inst.less_eq_nat},
236 @{const_name Nat.ord_nat_inst.less_nat},
237 @{const_name number_nat_inst.number_of_nat},
238 @{const_name Int.Bit0},
239 @{const_name Int.Bit1},
240 @{const_name Int.Pls},
241 @{const_name Int.zero_int_inst.zero_int},
242 @{const_name List.filter},
243 @{const_name HOL.If},
244 @{const_name Groups.minus}
248 fun print_specification options thy constname specs =
249 if show_intermediate_results options then
250 tracing ("Specification of " ^ constname ^ ":\n" ^
251 cat_lines (map (Display.string_of_thm_global thy) specs))
254 fun obtain_specification_graph options thy t =
256 val ctxt = ProofContext.init_global thy
257 fun is_nondefining_const (c, T) = member (op =) logic_operator_names c
258 fun has_code_pred_intros (c, T) = can (Predicate_Compile_Core.intros_of ctxt) c
259 fun case_consts (c, T) = is_some (Datatype.info_of_case thy c)
260 fun is_datatype_constructor (c, T) = is_some (Datatype.info_of_constr thy (c, T))
261 fun defiants_of specs =
262 fold (Term.add_consts o prop_of) specs []
263 |> filter_out is_datatype_constructor
264 |> filter_out is_nondefining_const
265 |> filter_out has_code_pred_intros
266 |> filter_out case_consts
267 |> filter_out special_cases
268 |> filter_out (fn (c, _) => Symtab.defined (#ignore_consts (Data.get thy)) c)
269 |> map (fn (c, _) => (c, Sign.the_const_constraint thy c))
272 |> filter is_defining_constname*)
274 if can (Term_Graph.get_node gr) t then gr
277 val specs = get_specification options thy t
278 (*|> Predicate_Compile_Set.unfold_set_notation*)
279 (*val _ = print_specification options thy constname specs*)
280 val us = defiants_of specs
283 |> Term_Graph.new_node (t, specs)
285 |> fold (fn u => Term_Graph.add_edge (t, u)) us
288 extend t Term_Graph.empty
292 fun present_graph gr =
294 fun eq_cname (Const (c1, _), Const (c2, _)) = (c1 = c2)
295 fun string_of_const (Const (c, _)) = c
296 | string_of_const _ = error "string_of_const: unexpected term"
297 val constss = Term_Graph.strong_conn gr;
298 val mapping = Termtab.empty |> fold (fn consts => fold (fn const =>
299 Termtab.update (const, consts)) consts) constss;
300 fun succs consts = consts
301 |> maps (Term_Graph.imm_succs gr)
302 |> subtract eq_cname consts
303 |> map (the o Termtab.lookup mapping)
304 |> distinct (eq_list eq_cname);
305 val conn = [] |> fold (fn consts => cons (consts, succs consts)) constss;
307 fun namify consts = map string_of_const consts
309 val prgr = map (fn (consts, constss) =>
310 { name = namify consts, ID = namify consts, dir = "", unfold = true,
311 path = "", parents = map namify constss }) conn;
312 in Present.display_graph prgr end;