1 (* Title: HOL/Tools/Lifting/lifting_setup.ML
4 Setting up the lifting infrastructure.
7 signature LIFTING_SETUP =
9 exception SETUP_LIFTING_INFR of string
11 val setup_by_quotient: bool -> thm -> thm option -> local_theory -> local_theory
13 val setup_by_typedef_thm: bool -> thm -> local_theory -> local_theory
16 structure Lifting_Setup: LIFTING_SETUP =
23 exception SETUP_LIFTING_INFR of string
25 fun define_cr_rel rep_fun lthy =
27 val (qty, rty) = (dest_funT o fastype_of) rep_fun
28 val rep_fun_graph = (HOLogic.eq_const rty) $ Bound 1 $ (rep_fun $ Bound 0)
29 val def_term = Abs ("x", rty, Abs ("y", qty, rep_fun_graph));
30 val qty_name = (fst o dest_Type) qty
31 val cr_rel_name = Binding.prefix_name "cr_" (Binding.qualified_name qty_name)
32 val (fixed_def_term, lthy') = yield_singleton (Variable.importT_terms) def_term lthy
33 val ((_, (_ , def_thm)), lthy'') =
34 Local_Theory.define ((cr_rel_name, NoSyn), ((Thm.def_binding cr_rel_name, []), fixed_def_term)) lthy'
39 fun define_code_constr gen_code quot_thm lthy =
41 val abs = quot_thm_abs quot_thm
42 val abs_background = Morphism.term (Local_Theory.target_morphism lthy) abs
44 if gen_code andalso is_Const abs_background then
46 val (const_name, typ) = dest_Const abs_background
47 val fake_term = Logic.mk_type typ
48 val (fixed_fake_term, lthy') = yield_singleton(Variable.importT_terms) fake_term lthy
49 val fixed_type = Logic.dest_type fixed_fake_term
51 Local_Theory.background_theory(Code.add_datatype [(const_name, fixed_type)]) lthy'
57 fun define_abs_type gen_code quot_thm lthy =
58 if gen_code andalso Lifting_Def.can_generate_code_cert quot_thm then
60 val abs_type_thm = quot_thm RS @{thm Quotient_abs_rep}
61 val add_abstype_attribute =
62 Thm.declaration_attribute (fn thm => Context.mapping (Code.add_abstype thm) I)
63 val add_abstype_attrib = Attrib.internal (K add_abstype_attribute);
66 |> (snd oo Local_Theory.note) ((Binding.empty, [add_abstype_attrib]), [abs_type_thm])
71 fun quot_thm_sanity_check ctxt quot_thm =
73 val ((_, [quot_thm_fixed]), ctxt') = Variable.importT [quot_thm] ctxt
74 val (rty, qty) = quot_thm_rty_qty quot_thm_fixed
75 val rty_tfreesT = Term.add_tfree_namesT rty []
76 val qty_tfreesT = Term.add_tfree_namesT qty []
77 val extra_rty_tfrees =
78 case subtract (op =) qty_tfreesT rty_tfreesT of
80 | extras => [Pretty.block ([Pretty.str "Extra variables in the raw type:",
82 ((Pretty.commas o map (Pretty.str o quote)) extras) @
87 | _ => [Pretty.block [Pretty.str "The quotient type ",
88 Pretty.quote (Syntax.pretty_typ ctxt' qty),
90 Pretty.str "is not a type constructor."]]
91 val errs = extra_rty_tfrees @ not_type_constr
93 if null errs then () else error (cat_lines (["Sanity check of the quotient theorem failed:",""]
94 @ (map Pretty.string_of errs)))
97 fun setup_lifting_infr gen_code quot_thm maybe_reflp_thm lthy =
99 val _ = quot_thm_sanity_check lthy quot_thm
100 val (_, qtyp) = quot_thm_rty_qty quot_thm
101 val qty_full_name = (fst o dest_Type) qtyp
102 val quotients = { quot_thm = quot_thm }
103 fun quot_info phi = Lifting_Info.transform_quotients phi quotients
104 val lthy' = case maybe_reflp_thm of
105 SOME reflp_thm => lthy
106 |> (snd oo Local_Theory.note) ((Binding.empty, [Lifting_Info.add_reflp_preserve_rule_attrib]),
108 |> define_code_constr gen_code quot_thm
110 |> define_abs_type gen_code quot_thm
113 |> Local_Theory.declaration {syntax = false, pervasive = true}
114 (fn phi => Lifting_Info.update_quotients qty_full_name (quot_info phi))
118 Sets up the Lifting package by a quotient theorem.
120 gen_code - flag if an abstract type given by quot_thm should be registred
121 as an abstract type in the code generator
122 quot_thm - a quotient theorem (Quotient R Abs Rep T)
123 maybe_reflp_thm - a theorem saying that a relation from quot_thm is reflexive
124 (in the form "reflp R")
127 fun setup_by_quotient gen_code quot_thm maybe_reflp_thm lthy =
129 val transfer_attr = Attrib.internal (K Transfer.transfer_add)
130 val (_, qty) = quot_thm_rty_qty quot_thm
131 val induct_attr = Attrib.internal (K (Induct.induct_type (fst (dest_Type qty))))
132 val qty_name = (Binding.name o Long_Name.base_name o fst o dest_Type) qty
133 fun qualify suffix = Binding.qualified true suffix qty_name
134 val lthy' = case maybe_reflp_thm of
135 SOME reflp_thm => lthy
136 |> (snd oo Local_Theory.note) ((qualify "bi_total", [transfer_attr]),
137 [[quot_thm, reflp_thm] MRSL @{thm Quotient_bi_total}])
138 |> (snd oo Local_Theory.note) ((qualify "id_abs_transfer", [transfer_attr]),
139 [[quot_thm, reflp_thm] MRSL @{thm Quotient_id_abs_transfer}])
140 |> (snd oo Local_Theory.note) ((qualify "abs_induct", [induct_attr]),
141 [[quot_thm, reflp_thm] MRSL @{thm Quotient_total_abs_induct}])
142 |> (snd oo Local_Theory.note) ((qualify "abs_eq_iff", []),
143 [[quot_thm, reflp_thm] MRSL @{thm Quotient_total_abs_eq_iff}])
145 |> (snd oo Local_Theory.note) ((qualify "All_transfer", [transfer_attr]),
146 [quot_thm RS @{thm Quotient_All_transfer}])
147 |> (snd oo Local_Theory.note) ((qualify "Ex_transfer", [transfer_attr]),
148 [quot_thm RS @{thm Quotient_Ex_transfer}])
149 |> (snd oo Local_Theory.note) ((qualify "forall_transfer", [transfer_attr]),
150 [quot_thm RS @{thm Quotient_forall_transfer}])
151 |> (snd oo Local_Theory.note) ((qualify "abs_induct", [induct_attr]),
152 [quot_thm RS @{thm Quotient_abs_induct}])
155 |> (snd oo Local_Theory.note) ((qualify "right_unique", [transfer_attr]),
156 [quot_thm RS @{thm Quotient_right_unique}])
157 |> (snd oo Local_Theory.note) ((qualify "right_total", [transfer_attr]),
158 [quot_thm RS @{thm Quotient_right_total}])
159 |> (snd oo Local_Theory.note) ((qualify "rel_eq_transfer", [transfer_attr]),
160 [quot_thm RS @{thm Quotient_rel_eq_transfer}])
161 |> setup_lifting_infr gen_code quot_thm maybe_reflp_thm
165 Sets up the Lifting package by a typedef theorem.
167 gen_code - flag if an abstract type given by typedef_thm should be registred
168 as an abstract type in the code generator
169 typedef_thm - a typedef theorem (type_definition Rep Abs S)
172 fun setup_by_typedef_thm gen_code typedef_thm lthy =
174 val transfer_attr = Attrib.internal (K Transfer.transfer_add)
175 val (_ $ rep_fun $ _ $ typedef_set) = (HOLogic.dest_Trueprop o prop_of) typedef_thm
176 val (T_def, lthy') = define_cr_rel rep_fun lthy
178 val quot_thm = case typedef_set of
179 Const ("Orderings.top_class.top", _) =>
180 [typedef_thm, T_def] MRSL @{thm UNIV_typedef_to_Quotient}
181 | Const (@{const_name "Collect"}, _) $ Abs (_, _, _) =>
182 [typedef_thm, T_def] MRSL @{thm open_typedef_to_Quotient}
184 [typedef_thm, T_def] MRSL @{thm typedef_to_Quotient}
186 val (_, qty) = quot_thm_rty_qty quot_thm
187 val qty_name = (Binding.name o Long_Name.base_name o fst o dest_Type) qty
188 fun qualify suffix = Binding.qualified true suffix qty_name
189 val simplify = Raw_Simplifier.rewrite_rule [mk_meta_eq @{thm mem_Collect_eq}]
191 val (maybe_reflp_thm, lthy'') = case typedef_set of
192 Const ("Orderings.top_class.top", _) =>
194 val equivp_thm = typedef_thm RS @{thm UNIV_typedef_to_equivp}
195 val reflp_thm = equivp_thm RS @{thm equivp_reflp2}
198 |> (snd oo Local_Theory.note) ((qualify "bi_total", [transfer_attr]),
199 [[quot_thm, reflp_thm] MRSL @{thm Quotient_bi_total}])
200 |> (snd oo Local_Theory.note) ((qualify "id_abs_transfer", [transfer_attr]),
201 [[quot_thm, reflp_thm] MRSL @{thm Quotient_id_abs_transfer}])
202 |> pair (SOME reflp_thm)
205 |> (snd oo Local_Theory.note) ((qualify "All_transfer", [transfer_attr]),
206 [[typedef_thm, T_def] MRSL @{thm typedef_All_transfer}])
207 |> (snd oo Local_Theory.note) ((qualify "Ex_transfer", [transfer_attr]),
208 [[typedef_thm, T_def] MRSL @{thm typedef_Ex_transfer}])
209 |> (snd oo Local_Theory.note) ((qualify "forall_transfer", [transfer_attr]),
210 [simplify ([typedef_thm, T_def] MRSL @{thm typedef_forall_transfer})])
214 |> (snd oo Local_Theory.note) ((Binding.prefix_name "Quotient_" qty_name, []),
216 |> (snd oo Local_Theory.note) ((qualify "bi_unique", [transfer_attr]),
217 [[typedef_thm, T_def] MRSL @{thm typedef_bi_unique}])
218 |> (snd oo Local_Theory.note) ((qualify "rep_transfer", [transfer_attr]),
219 [[typedef_thm, T_def] MRSL @{thm typedef_rep_transfer}])
220 |> (snd oo Local_Theory.note) ((qualify "right_unique", [transfer_attr]),
221 [[quot_thm] MRSL @{thm Quotient_right_unique}])
222 |> (snd oo Local_Theory.note) ((qualify "right_total", [transfer_attr]),
223 [[quot_thm] MRSL @{thm Quotient_right_total}])
224 |> setup_lifting_infr gen_code quot_thm maybe_reflp_thm
227 fun setup_lifting_cmd gen_code xthm opt_reflp_xthm lthy =
229 val input_thm = singleton (Attrib.eval_thms lthy) xthm
230 val input_term = (HOLogic.dest_Trueprop o prop_of) input_thm
231 handle TERM _ => error "Unsupported type of a theorem. Only Quotient or type_definition are supported."
233 fun sanity_check_reflp_thm reflp_thm =
235 val reflp_tm = (HOLogic.dest_Trueprop o prop_of) reflp_thm
236 handle TERM _ => error "Invalid form of the reflexivity theorem. Use \"reflp R\"."
239 Const (@{const_name reflp}, _) $ _ => ()
240 | _ => error "Invalid form of the reflexivity theorem. Use \"reflp R\"."
243 fun setup_quotient () =
244 case opt_reflp_xthm of
247 val reflp_thm = singleton (Attrib.eval_thms lthy) reflp_xthm
248 val _ = sanity_check_reflp_thm reflp_thm
250 setup_by_quotient gen_code input_thm (SOME reflp_thm) lthy
252 | NONE => setup_by_quotient gen_code input_thm NONE lthy
254 fun setup_typedef () =
255 case opt_reflp_xthm of
256 SOME _ => error "The reflexivity theorem cannot be specified if the type_definition theorem is used."
257 | NONE => setup_by_typedef_thm gen_code input_thm lthy
260 (Const (@{const_name Quotient}, _) $ _ $ _ $ _ $ _) => setup_quotient ()
261 | (Const (@{const_name type_definition}, _) $ _ $ _ $ _) => setup_typedef ()
262 | _ => error "Unsupported type of a theorem. Only Quotient or type_definition are supported."
266 Scan.optional (@{keyword "("} |-- Parse.!!! ((Parse.reserved "no_code" >> K false) --| @{keyword ")"})) true
269 Outer_Syntax.local_theory @{command_spec "setup_lifting"}
270 "Setup lifting infrastructure"
271 (opt_gen_code -- Parse_Spec.xthm -- Scan.option Parse_Spec.xthm >>
272 (fn ((gen_code, xthm), opt_reflp_xthm) => setup_lifting_cmd gen_code xthm opt_reflp_xthm))