src/HOL/Tools/Lifting/lifting_setup.ML
author kuncar
Fri, 11 Oct 2013 18:36:51 +0200
changeset 55221 ce028cf2e58e
parent 54891 124bb918f45f
child 55223 03b10317ba78
permissions -rw-r--r--
don't allow parametricity theorem for typedefs in setup_lifting. The theorem is not used.
     1 (*  Title:      HOL/Tools/Lifting/lifting_setup.ML
     2     Author:     Ondrej Kuncar
     3 
     4 Setting up the lifting infrastructure.
     5 *)
     6 
     7 signature LIFTING_SETUP =
     8 sig
     9   exception SETUP_LIFTING_INFR of string
    10 
    11   val setup_by_quotient: bool -> thm -> thm option -> thm option -> local_theory -> local_theory
    12 
    13   val setup_by_typedef_thm: bool -> thm -> local_theory -> local_theory
    14 
    15   val lifting_restore: Lifting_Info.quotient -> Context.generic -> Context.generic
    16 end
    17 
    18 structure Lifting_Setup: LIFTING_SETUP =
    19 struct
    20 
    21 open Lifting_Util
    22 
    23 infix 0 MRSL
    24 
    25 exception SETUP_LIFTING_INFR of string
    26 
    27 fun define_crel rep_fun lthy =
    28   let
    29     val (qty, rty) = (dest_funT o fastype_of) rep_fun
    30     val rep_fun_graph = (HOLogic.eq_const rty) $ Bound 1 $ (rep_fun $ Bound 0)
    31     val def_term = Abs ("x", rty, Abs ("y", qty, rep_fun_graph))
    32     val qty_name = (Binding.name o Long_Name.base_name o fst o dest_Type) qty
    33     val crel_name = Binding.prefix_name "cr_" qty_name
    34     val (fixed_def_term, lthy') = yield_singleton (Variable.importT_terms) def_term lthy
    35     val ((_, (_ , def_thm)), lthy'') =
    36       Local_Theory.define ((crel_name, NoSyn), ((Thm.def_binding crel_name, []), fixed_def_term)) lthy'
    37   in
    38     (def_thm, lthy'')
    39   end
    40 
    41 fun print_define_pcrel_warning msg = 
    42   let
    43     val warning_msg = cat_lines 
    44       ["Generation of a parametrized correspondence relation failed.",
    45       (Pretty.string_of (Pretty.block
    46          [Pretty.str "Reason:", Pretty.brk 2, msg]))]
    47   in
    48     warning warning_msg
    49   end
    50 
    51 fun define_pcrel crel lthy =
    52   let
    53     val (fixed_crel, lthy) = yield_singleton Variable.importT_terms crel lthy
    54     val [rty', qty] = (binder_types o fastype_of) fixed_crel
    55     val (param_rel, args) = Lifting_Term.generate_parametrized_relator lthy rty'
    56     val rty_raw = (domain_type o range_type o fastype_of) param_rel
    57     val thy = Proof_Context.theory_of lthy
    58     val tyenv_match = Sign.typ_match thy (rty_raw, rty') Vartab.empty
    59     val param_rel_subst = Envir.subst_term (tyenv_match,Vartab.empty) param_rel
    60     val args_subst = map (Envir.subst_term (tyenv_match,Vartab.empty)) args
    61     val lthy = Variable.declare_names fixed_crel lthy
    62     val (instT, lthy) = Variable.importT_inst (param_rel_subst :: args_subst) lthy
    63     val args_fixed = (map (Term_Subst.instantiate (instT, []))) args_subst
    64     val param_rel_fixed = Term_Subst.instantiate (instT, []) param_rel_subst
    65     val rty = (domain_type o fastype_of) param_rel_fixed
    66     val relcomp_op = Const (@{const_name "relcompp"}, 
    67           (rty --> rty' --> HOLogic.boolT) --> 
    68           (rty' --> qty --> HOLogic.boolT) --> 
    69           rty --> qty --> HOLogic.boolT)
    70     val relator_type = foldr1 (op -->) ((map type_of args_fixed) @ [rty, qty, HOLogic.boolT])
    71     val qty_name = (fst o dest_Type) qty
    72     val pcrel_name = Binding.prefix_name "pcr_" ((Binding.name o Long_Name.base_name) qty_name)
    73     val lhs = Library.foldl (op $) ((Free (Binding.name_of pcrel_name, relator_type)), args_fixed)
    74     val rhs = relcomp_op $ param_rel_fixed $ fixed_crel
    75     val definition_term = Logic.mk_equals (lhs, rhs)
    76     val ((_, (_, def_thm)), lthy) = Specification.definition ((SOME (pcrel_name, SOME relator_type, NoSyn)), 
    77       ((Binding.empty, []), definition_term)) lthy
    78   in
    79     (SOME def_thm, lthy)
    80   end
    81   handle Lifting_Term.PARAM_QUOT_THM (_, msg) => (print_define_pcrel_warning msg; (NONE, lthy))
    82 
    83 
    84 local
    85   val eq_OO_meta = mk_meta_eq @{thm eq_OO} 
    86 
    87   fun print_generate_pcr_cr_eq_error ctxt term = 
    88   let
    89     val goal = (Const ("HOL.eq", dummyT)) $ term $ Const ("HOL.eq", dummyT)
    90     val error_msg = cat_lines 
    91       ["Generation of a pcr_cr_eq failed.",
    92       (Pretty.string_of (Pretty.block
    93          [Pretty.str "Reason: Cannot prove this: ", Pretty.brk 2, Syntax.pretty_term ctxt goal])),
    94        "Most probably a relator_eq rule for one of the involved types is missing."]
    95   in
    96     error error_msg
    97   end
    98 in
    99   fun define_pcr_cr_eq lthy pcr_rel_def =
   100     let
   101       val lhs = (term_of o Thm.lhs_of) pcr_rel_def
   102       val qty_name = (Binding.name o Long_Name.base_name o fst o dest_Type o List.last o binder_types o fastype_of) lhs
   103       val args = (snd o strip_comb) lhs
   104       
   105       fun make_inst var ctxt = 
   106         let 
   107           val typ = (snd o relation_types o snd o dest_Var) var
   108           val sort = Type.sort_of_atyp typ
   109           val (fresh_var, ctxt) = yield_singleton Variable.invent_types sort ctxt
   110           val thy = Proof_Context.theory_of ctxt
   111         in
   112           ((cterm_of thy var, cterm_of thy (HOLogic.eq_const (TFree fresh_var))), ctxt)
   113         end
   114       
   115       val orig_lthy = lthy
   116       val (args_inst, lthy) = fold_map make_inst args lthy
   117       val pcr_cr_eq = 
   118         pcr_rel_def
   119         |> Drule.cterm_instantiate args_inst    
   120         |> Conv.fconv_rule (Conv.arg_conv (Conv.arg1_conv 
   121           (Transfer.bottom_rewr_conv (Transfer.get_relator_eq lthy))))
   122   in
   123     case (term_of o Thm.rhs_of) pcr_cr_eq of
   124       Const (@{const_name "relcompp"}, _) $ Const ("HOL.eq", _) $ _ => 
   125         let
   126           val thm = 
   127             pcr_cr_eq
   128             |> Conv.fconv_rule (Conv.arg_conv (Conv.rewr_conv eq_OO_meta))
   129             |> mk_HOL_eq
   130             |> singleton (Variable.export lthy orig_lthy)
   131           val ((_, [thm]), lthy) = Local_Theory.note ((Binding.qualified true "pcr_cr_eq" qty_name, []), 
   132             [thm]) lthy
   133         in
   134           (thm, lthy)
   135         end
   136       | Const (@{const_name "relcompp"}, _) $ t $ _ => print_generate_pcr_cr_eq_error lthy t
   137       | _ => error "generate_pcr_cr_eq: implementation error"
   138   end
   139 end
   140 
   141 fun define_code_constr gen_code quot_thm lthy =
   142   let
   143     val abs = quot_thm_abs quot_thm
   144   in
   145     if gen_code andalso is_Const abs then
   146       let
   147         val (fixed_abs, lthy') = yield_singleton(Variable.importT_terms) abs lthy
   148       in  
   149          Local_Theory.background_theory(Code.add_datatype [dest_Const fixed_abs]) lthy'
   150       end
   151     else
   152       lthy
   153   end
   154 
   155 fun define_abs_type gen_code quot_thm lthy =
   156   if gen_code andalso Lifting_Def.can_generate_code_cert quot_thm then
   157     let
   158       val abs_type_thm = quot_thm RS @{thm Quotient_abs_rep}
   159       val add_abstype_attribute = 
   160           Thm.declaration_attribute (fn thm => Context.mapping (Code.add_abstype thm) I)
   161         val add_abstype_attrib = Attrib.internal (K add_abstype_attribute)
   162     in
   163       lthy
   164         |> (snd oo Local_Theory.note) ((Binding.empty, [add_abstype_attrib]), [abs_type_thm])
   165     end
   166   else
   167     lthy
   168 
   169 local
   170   exception QUOT_ERROR of Pretty.T list
   171 in
   172 fun quot_thm_sanity_check ctxt quot_thm =
   173   let
   174     val _ = 
   175       if (nprems_of quot_thm > 0) then   
   176           raise QUOT_ERROR [Pretty.block
   177             [Pretty.str "The Quotient theorem has extra assumptions:",
   178              Pretty.brk 1,
   179              Display.pretty_thm ctxt quot_thm]]
   180       else ()
   181     val _ = quot_thm |> concl_of |> HOLogic.dest_Trueprop |> dest_Quotient
   182     handle TERM _ => raise QUOT_ERROR
   183           [Pretty.block
   184             [Pretty.str "The Quotient theorem is not of the right form:",
   185              Pretty.brk 1,
   186              Display.pretty_thm ctxt quot_thm]]
   187     val ((_, [quot_thm_fixed]), ctxt') = Variable.importT [quot_thm] ctxt 
   188     val (rty, qty) = quot_thm_rty_qty quot_thm_fixed
   189     val rty_tfreesT = Term.add_tfree_namesT rty []
   190     val qty_tfreesT = Term.add_tfree_namesT qty []
   191     val extra_rty_tfrees =
   192       case subtract (op =) qty_tfreesT rty_tfreesT of
   193         [] => []
   194       | extras => [Pretty.block ([Pretty.str "Extra variables in the raw type:",
   195                                  Pretty.brk 1] @ 
   196                                  ((Pretty.commas o map (Pretty.str o quote)) extras) @
   197                                  [Pretty.str "."])]
   198     val not_type_constr = 
   199       case qty of
   200          Type _ => []
   201          | _ => [Pretty.block [Pretty.str "The quotient type ",
   202                                 Pretty.quote (Syntax.pretty_typ ctxt' qty),
   203                                 Pretty.brk 1,
   204                                 Pretty.str "is not a type constructor."]]
   205     val errs = extra_rty_tfrees @ not_type_constr
   206   in
   207     if null errs then () else raise QUOT_ERROR errs
   208   end
   209   handle QUOT_ERROR errs => error (cat_lines (["Sanity check of the quotient theorem failed:"] 
   210                                             @ (map (Pretty.string_of o Pretty.item o single) errs)))
   211 end
   212 
   213 fun lifting_bundle qty_full_name qinfo lthy = 
   214   let
   215     fun qualify suffix defname = Binding.qualified true suffix defname
   216     val binding =  qty_full_name |> Long_Name.base_name |> Binding.name |> qualify "lifting"
   217     val morphed_binding = Morphism.binding (Local_Theory.target_morphism lthy) binding
   218     val bundle_name = Name_Space.full_name (Name_Space.naming_of 
   219       (Context.Theory (Proof_Context.theory_of lthy))) morphed_binding
   220     fun phi_qinfo phi = Lifting_Info.transform_quotient phi qinfo
   221 
   222     val thy = Proof_Context.theory_of lthy
   223     val dummy_thm = Thm.transfer thy Drule.dummy_thm
   224     val pointer = Outer_Syntax.scan Position.none bundle_name
   225     val restore_lifting_att = 
   226       ([dummy_thm], [Args.src (("Lifting.lifting_restore_internal", pointer), Position.none)])
   227   in
   228     lthy 
   229       |> Local_Theory.declaration {syntax = false, pervasive = true}
   230            (fn phi => Lifting_Info.init_restore_data bundle_name (phi_qinfo phi))
   231       |> Bundle.bundle ((binding, [restore_lifting_att])) []
   232   end
   233 
   234 fun setup_lifting_infr gen_code quot_thm opt_reflp_thm lthy =
   235   let
   236     val _ = quot_thm_sanity_check lthy quot_thm
   237     val (_, qtyp) = quot_thm_rty_qty quot_thm
   238     val (pcrel_def, lthy) = define_pcrel (quot_thm_crel quot_thm) lthy
   239     (**)
   240     val pcrel_def = Option.map (Morphism.thm (Local_Theory.target_morphism lthy)) pcrel_def
   241     (**)
   242     val (pcr_cr_eq, lthy) = case pcrel_def of
   243       SOME pcrel_def => apfst SOME (define_pcr_cr_eq lthy pcrel_def)
   244       | NONE => (NONE, lthy)
   245     val pcr_info = case pcrel_def of
   246       SOME pcrel_def => SOME { pcrel_def = pcrel_def, pcr_cr_eq = the pcr_cr_eq }
   247       | NONE => NONE
   248     val quotients = { quot_thm = quot_thm, pcr_info = pcr_info }
   249     val qty_full_name = (fst o dest_Type) qtyp  
   250     fun quot_info phi = Lifting_Info.transform_quotient phi quotients
   251     val reflexivity_rule_attr = Attrib.internal (K Lifting_Info.add_reflexivity_rule_attribute)
   252     val lthy = case opt_reflp_thm of
   253       SOME reflp_thm => lthy
   254         |> (snd oo Local_Theory.note) ((Binding.empty, [reflexivity_rule_attr]),
   255               [reflp_thm])
   256         |> (snd oo Local_Theory.note) ((Binding.empty, [reflexivity_rule_attr]),
   257               [[quot_thm, reflp_thm] MRSL @{thm Quotient_to_left_total}])
   258         |> define_code_constr gen_code quot_thm
   259       | NONE => lthy
   260         |> define_abs_type gen_code quot_thm
   261   in
   262     lthy
   263       |> Local_Theory.declaration {syntax = false, pervasive = true}
   264         (fn phi => Lifting_Info.update_quotients qty_full_name (quot_info phi))
   265       |> lifting_bundle qty_full_name quotients
   266   end
   267 
   268 local
   269   fun importT_inst_exclude exclude ts ctxt =
   270     let
   271       val tvars = rev (subtract op= exclude (fold Term.add_tvars ts []))
   272       val (tfrees, ctxt') = Variable.invent_types (map #2 tvars) ctxt
   273     in (tvars ~~ map TFree tfrees, ctxt') end
   274   
   275   fun import_inst_exclude exclude ts ctxt =
   276     let
   277       val excludeT = fold (Term.add_tvarsT o snd) exclude []
   278       val (instT, ctxt') = importT_inst_exclude excludeT ts ctxt
   279       val vars = map (apsnd (Term_Subst.instantiateT instT)) 
   280         (rev (subtract op= exclude (fold Term.add_vars ts [])))
   281       val (xs, ctxt'') = Variable.variant_fixes (map (#1 o #1) vars) ctxt'
   282       val inst = vars ~~ map Free (xs ~~ map #2 vars)
   283     in ((instT, inst), ctxt'') end
   284   
   285   fun import_terms_exclude exclude ts ctxt =
   286     let val (inst, ctxt') = import_inst_exclude exclude ts ctxt
   287     in (map (Term_Subst.instantiate inst) ts, ctxt') end
   288 in
   289   fun reduce_goal not_fix goal tac ctxt =
   290     let
   291       val thy = Proof_Context.theory_of ctxt
   292       val orig_ctxt = ctxt
   293       val (fixed_goal, ctxt) = yield_singleton (import_terms_exclude not_fix) goal ctxt
   294       val init_goal = Goal.init (cterm_of thy fixed_goal)
   295     in
   296       (singleton (Variable.export ctxt orig_ctxt) o Goal.conclude) (the (SINGLE tac init_goal))
   297     end
   298 end
   299 
   300 local 
   301   val OO_rules = [@{thm bi_total_OO}, @{thm bi_unique_OO}, @{thm right_total_OO}, @{thm right_unique_OO}]
   302 in
   303   fun parametrize_class_constraint ctxt pcr_def constraint =
   304     let
   305       fun generate_transfer_rule pcr_def constraint goal ctxt =
   306         let
   307           val thy = Proof_Context.theory_of ctxt
   308           val orig_ctxt = ctxt
   309           val (fixed_goal, ctxt) = yield_singleton (Variable.import_terms true) goal ctxt
   310           val init_goal = Goal.init (cterm_of thy fixed_goal)
   311           val rules = Transfer.get_transfer_raw ctxt
   312           val rules = constraint :: OO_rules @ rules
   313           val tac = K (Local_Defs.unfold_tac ctxt [pcr_def]) THEN' REPEAT_ALL_NEW (resolve_tac rules)
   314         in
   315           (singleton (Variable.export ctxt orig_ctxt) o Goal.conclude) (the (SINGLE (tac 1) init_goal))
   316         end
   317       
   318       fun make_goal pcr_def constr =
   319         let 
   320           val pred_name = (fst o dest_Const o strip_args 1 o HOLogic.dest_Trueprop o prop_of) constr
   321           val arg = (fst o Logic.dest_equals o prop_of) pcr_def
   322         in
   323           HOLogic.mk_Trueprop ((Const (pred_name, (fastype_of arg) --> HOLogic.boolT)) $ arg)
   324         end
   325       
   326       val check_assms =
   327         let 
   328           val right_names = ["bi_total", "bi_unique", "right_total", "right_unique"]
   329       
   330           fun is_right_name name = member op= right_names (Long_Name.base_name name)
   331       
   332           fun is_trivial_assm (Const (name, _) $ Var (_, _)) = is_right_name name
   333             | is_trivial_assm (Const (name, _) $ Free (_, _)) = is_right_name name
   334             | is_trivial_assm _ = false
   335         in
   336           fn thm => 
   337             let
   338               val prems = map HOLogic.dest_Trueprop (prems_of thm)
   339               val thm_name = (Long_Name.base_name o fst o dest_Const o strip_args 1 o HOLogic.dest_Trueprop o concl_of) thm
   340               val non_trivial_assms = filter_out is_trivial_assm prems
   341             in
   342               if null non_trivial_assms then ()
   343               else
   344                 let
   345                   val pretty_msg = Pretty.block ([Pretty.str "Non-trivial assumptions in ",
   346                     Pretty.str thm_name,
   347                     Pretty.str " transfer rule found:",
   348                     Pretty.brk 1] @ 
   349                     ((Pretty.commas o map (Syntax.pretty_term ctxt)) non_trivial_assms) @
   350                                        [Pretty.str "."])
   351                 in
   352                   warning (Pretty.str_of pretty_msg)
   353                 end
   354             end
   355         end
   356   
   357       val goal = make_goal pcr_def constraint
   358       val thm = generate_transfer_rule pcr_def constraint goal ctxt
   359       val _ = check_assms thm
   360     in
   361       thm
   362     end
   363 end
   364 
   365 local
   366   val id_unfold = (Conv.rewr_conv (mk_meta_eq @{thm id_def}))
   367 in
   368   fun generate_parametric_id lthy rty id_transfer_rule =
   369     let
   370       val orig_lthy = lthy
   371       (* it doesn't raise an exception because it would have already raised it in define_pcrel *)
   372       val (quot_thm, _, lthy) = Lifting_Term.prove_param_quot_thm lthy rty
   373       val parametrized_relator = singleton (Variable.export_terms lthy orig_lthy) (quot_thm_crel quot_thm)
   374       val lthy = orig_lthy
   375       val id_transfer = 
   376          @{thm id_transfer}
   377         |> Thm.incr_indexes (Term.maxidx_of_term parametrized_relator + 1)
   378         |> Conv.fconv_rule(HOLogic.Trueprop_conv (Conv.arg_conv id_unfold then_conv Conv.arg1_conv id_unfold))
   379       val var = Var (hd (Term.add_vars (prop_of id_transfer) []))
   380       val thy = Proof_Context.theory_of lthy
   381       val inst = [(cterm_of thy var, cterm_of thy parametrized_relator)]
   382       val id_par_thm = Drule.cterm_instantiate inst id_transfer
   383     in
   384       Lifting_Def.generate_parametric_transfer_rule lthy id_transfer_rule id_par_thm
   385     end
   386     handle Lifting_Term.MERGE_TRANSFER_REL msg => 
   387       let
   388         val error_msg = cat_lines 
   389           ["Generation of a parametric transfer rule for the abs. or the rep. function failed.",
   390           "A non-parametric version will be used.",
   391           (Pretty.string_of (Pretty.block
   392              [Pretty.str "Reason:", Pretty.brk 2, msg]))]
   393       in
   394         (warning error_msg; id_transfer_rule)
   395       end
   396 end
   397 
   398 local
   399   fun rewrite_first_Domainp_arg rewr_thm thm = Conv.fconv_rule (Conv.concl_conv ~1 (HOLogic.Trueprop_conv 
   400       (Conv.arg1_conv (Conv.arg_conv (Conv.rewr_conv rewr_thm))))) thm
   401   
   402   fun fold_Domainp_pcrel pcrel_def thm =
   403     let
   404       val ct = thm |> cprop_of |> Drule.strip_imp_concl |> Thm.dest_arg |> Thm.dest_arg1 |> Thm.dest_arg
   405       val pcrel_def = Thm.incr_indexes (#maxidx (Thm.rep_cterm ct) + 1) pcrel_def
   406       val thm = Thm.instantiate (Thm.match (ct, Thm.rhs_of pcrel_def)) thm
   407         handle Pattern.MATCH => raise CTERM ("fold_Domainp_pcrel", [ct, Thm.rhs_of pcrel_def])
   408     in
   409       rewrite_first_Domainp_arg (Thm.symmetric pcrel_def) thm
   410     end
   411 
   412   fun reduce_Domainp ctxt rules thm =
   413     let
   414       val goal = thm |> prems_of |> hd
   415       val var = goal |> HOLogic.dest_Trueprop |> dest_comb |> snd |> dest_Var 
   416       val reduced_assm = reduce_goal [var] goal (TRY (REPEAT_ALL_NEW (resolve_tac rules) 1)) ctxt
   417     in
   418       reduced_assm RS thm
   419     end
   420 in
   421   fun parametrize_domain dom_thm (pcr_info : Lifting_Info.pcr) ctxt =
   422     let
   423       fun reduce_first_assm ctxt rules thm =
   424         let
   425           val goal = thm |> prems_of |> hd
   426           val reduced_assm = reduce_goal [] goal (TRY (REPEAT_ALL_NEW (resolve_tac rules) 1)) ctxt
   427         in
   428           reduced_assm RS thm
   429         end
   430 
   431       val pcr_cr_met_eq = #pcr_cr_eq pcr_info RS @{thm eq_reflection}
   432       val pcr_Domainp_eq = rewrite_first_Domainp_arg (Thm.symmetric pcr_cr_met_eq) dom_thm
   433       val pcrel_def = #pcrel_def pcr_info
   434       val pcr_Domainp_par_left_total = 
   435         (dom_thm RS @{thm pcr_Domainp_par_left_total})
   436           |> fold_Domainp_pcrel pcrel_def
   437           |> reduce_first_assm ctxt (Lifting_Info.get_reflexivity_rules ctxt)
   438       val pcr_Domainp_par = 
   439         (dom_thm RS @{thm pcr_Domainp_par})      
   440           |> fold_Domainp_pcrel pcrel_def
   441           |> reduce_Domainp ctxt (Transfer.get_relator_domain ctxt)
   442       val pcr_Domainp = 
   443         (dom_thm RS @{thm pcr_Domainp})
   444           |> fold_Domainp_pcrel pcrel_def
   445       val thms =
   446         [("domain",                 pcr_Domainp),
   447          ("domain_par",             pcr_Domainp_par),
   448          ("domain_par_left_total",  pcr_Domainp_par_left_total),
   449          ("domain_eq",              pcr_Domainp_eq)]
   450     in
   451       thms
   452     end
   453 
   454   fun parametrize_total_domain bi_total pcrel_def ctxt =
   455     let
   456       val thm =
   457         (bi_total RS @{thm pcr_Domainp_total})
   458           |> fold_Domainp_pcrel pcrel_def 
   459           |> reduce_Domainp ctxt (Transfer.get_relator_domain ctxt)
   460     in
   461       [("domain", thm)]
   462     end
   463 
   464 end
   465 
   466 fun get_pcrel_info ctxt qty_full_name =  
   467   #pcr_info (the (Lifting_Info.lookup_quotients ctxt qty_full_name))
   468 
   469 fun get_Domainp_thm quot_thm =
   470    the (get_first (try(curry op RS quot_thm)) [@{thm invariant_to_Domainp}, @{thm Quotient_to_Domainp}])
   471 
   472 (*
   473   Sets up the Lifting package by a quotient theorem.
   474 
   475   gen_code - flag if an abstract type given by quot_thm should be registred 
   476     as an abstract type in the code generator
   477   quot_thm - a quotient theorem (Quotient R Abs Rep T)
   478   opt_reflp_thm - a theorem saying that a relation from quot_thm is reflexive
   479     (in the form "reflp R")
   480 *)
   481 
   482 fun setup_by_quotient gen_code quot_thm opt_reflp_thm opt_par_thm lthy =
   483   let
   484     (**)
   485     val quot_thm = Morphism.thm (Local_Theory.target_morphism lthy) quot_thm
   486     (**)
   487     val transfer_attr = Attrib.internal (K Transfer.transfer_add)
   488     val transfer_domain_attr = Attrib.internal (K Transfer.transfer_domain_add)
   489     val (rty, qty) = quot_thm_rty_qty quot_thm
   490     val induct_attr = Attrib.internal (K (Induct.induct_type (fst (dest_Type qty))))
   491     val qty_full_name = (fst o dest_Type) qty
   492     val qty_name = (Binding.name o Long_Name.base_name) qty_full_name
   493     fun qualify suffix = Binding.qualified true suffix qty_name
   494     val lthy = case opt_reflp_thm of
   495       SOME reflp_thm =>
   496         let 
   497           val thms =
   498             [("abs_induct",     @{thm Quotient_total_abs_induct}, [induct_attr]),
   499              ("abs_eq_iff",     @{thm Quotient_total_abs_eq_iff}, []           )]
   500         in
   501           lthy
   502             |> fold (fn (name, thm, attr) => (snd oo Local_Theory.note) ((qualify name, attr), 
   503               [[quot_thm, reflp_thm] MRSL thm])) thms
   504         end
   505       | NONE =>
   506         let
   507           val thms = 
   508             [("abs_induct",     @{thm Quotient_abs_induct},       [induct_attr])]
   509         in
   510           fold (fn (name, thm, attr) => (snd oo Local_Theory.note) ((qualify name, attr), 
   511             [quot_thm RS thm])) thms lthy
   512         end
   513     val dom_thm = get_Domainp_thm quot_thm
   514 
   515     fun setup_transfer_rules_nonpar lthy =
   516       let
   517         val lthy =
   518           case opt_reflp_thm of
   519             SOME reflp_thm =>
   520               let 
   521                 val thms =
   522                   [("id_abs_transfer",@{thm Quotient_id_abs_transfer}),
   523                    ("bi_total",       @{thm Quotient_bi_total}       )]
   524               in
   525                 fold (fn (name, thm) => (snd oo Local_Theory.note) ((qualify name, [transfer_attr]), 
   526                     [[quot_thm, reflp_thm] MRSL thm])) thms lthy
   527               end
   528             | NONE =>
   529               lthy
   530               |> (snd oo Local_Theory.note) ((qualify "domain", [transfer_domain_attr]), [dom_thm])
   531 
   532         val thms = 
   533           [("rel_eq_transfer", @{thm Quotient_rel_eq_transfer}),
   534            ("right_unique",    @{thm Quotient_right_unique}   ), 
   535            ("right_total",     @{thm Quotient_right_total}    )]
   536       in
   537         fold (fn (name, thm) => (snd oo Local_Theory.note) ((qualify name, [transfer_attr]), 
   538           [quot_thm RS thm])) thms lthy
   539       end
   540 
   541     fun generate_parametric_rel_eq lthy transfer_rule opt_param_thm =
   542       option_fold transfer_rule (Lifting_Def.generate_parametric_transfer_rule lthy transfer_rule) opt_param_thm
   543       handle Lifting_Term.MERGE_TRANSFER_REL msg => 
   544         let
   545           val error_msg = cat_lines 
   546             ["Generation of a parametric transfer rule for the quotient relation failed.",
   547             (Pretty.string_of (Pretty.block
   548                [Pretty.str "Reason:", Pretty.brk 2, msg]))]
   549         in
   550           error error_msg
   551         end
   552 
   553     fun setup_transfer_rules_par lthy =
   554       let
   555         val pcrel_info = (the (get_pcrel_info lthy qty_full_name))
   556         val pcrel_def = #pcrel_def pcrel_info
   557         val lthy =
   558           case opt_reflp_thm of
   559             SOME reflp_thm =>
   560               let
   561                 val bi_total = ([quot_thm, reflp_thm] MRSL @{thm Quotient_bi_total})
   562                 val domain_thms = parametrize_total_domain bi_total pcrel_def lthy
   563                 val id_abs_transfer = generate_parametric_id lthy rty
   564                   (Lifting_Term.parametrize_transfer_rule lthy
   565                     ([quot_thm, reflp_thm] MRSL @{thm Quotient_id_abs_transfer}))
   566                 val bi_total = parametrize_class_constraint lthy pcrel_def bi_total
   567                 val thms = 
   568                   [("id_abs_transfer",id_abs_transfer),
   569                    ("bi_total",       bi_total       )]
   570               in
   571                 lthy
   572                 |> fold (fn (name, thm) => (snd oo Local_Theory.note) ((qualify name, [transfer_attr]), 
   573                      [thm])) thms
   574                 |> fold (fn (name, thm) => (snd oo Local_Theory.note) ((qualify name, [transfer_domain_attr]), 
   575                      [thm])) domain_thms
   576               end
   577             | NONE =>
   578               let
   579                 val thms = parametrize_domain dom_thm pcrel_info lthy
   580               in
   581                 fold (fn (name, thm) => (snd oo Local_Theory.note) ((qualify name, [transfer_domain_attr]), 
   582                   [thm])) thms lthy
   583               end
   584 
   585         val rel_eq_transfer = generate_parametric_rel_eq lthy 
   586           (Lifting_Term.parametrize_transfer_rule lthy (quot_thm RS @{thm Quotient_rel_eq_transfer}))
   587             opt_par_thm
   588         val right_unique = parametrize_class_constraint lthy pcrel_def 
   589             (quot_thm RS @{thm Quotient_right_unique})
   590         val right_total = parametrize_class_constraint lthy pcrel_def 
   591             (quot_thm RS @{thm Quotient_right_total})
   592         val thms = 
   593           [("rel_eq_transfer", rel_eq_transfer),
   594            ("right_unique",    right_unique   ), 
   595            ("right_total",     right_total    )]      
   596       in
   597         fold (fn (name, thm) => (snd oo Local_Theory.note) ((qualify name, [transfer_attr]), 
   598           [thm])) thms lthy
   599       end
   600 
   601     fun setup_transfer_rules lthy = 
   602       if is_some (get_pcrel_info lthy qty_full_name) then setup_transfer_rules_par lthy
   603                                                      else setup_transfer_rules_nonpar lthy
   604   in
   605     lthy
   606       |> setup_lifting_infr gen_code quot_thm opt_reflp_thm
   607       |> setup_transfer_rules
   608   end
   609 
   610 (*
   611   Sets up the Lifting package by a typedef theorem.
   612 
   613   gen_code - flag if an abstract type given by typedef_thm should be registred 
   614     as an abstract type in the code generator
   615   typedef_thm - a typedef theorem (type_definition Rep Abs S)
   616 *)
   617 
   618 fun setup_by_typedef_thm gen_code typedef_thm lthy =
   619   let
   620     val transfer_attr = Attrib.internal (K Transfer.transfer_add)
   621     val transfer_domain_attr = Attrib.internal (K Transfer.transfer_domain_add)
   622     val (_ $ rep_fun $ _ $ typedef_set) = (HOLogic.dest_Trueprop o prop_of) typedef_thm
   623     val (T_def, lthy) = define_crel rep_fun lthy
   624     (**)
   625     val T_def = Morphism.thm (Local_Theory.target_morphism lthy) T_def
   626     (**)    
   627     val quot_thm = case typedef_set of
   628       Const ("Orderings.top_class.top", _) => 
   629         [typedef_thm, T_def] MRSL @{thm UNIV_typedef_to_Quotient}
   630       | Const (@{const_name "Collect"}, _) $ Abs (_, _, _) => 
   631         [typedef_thm, T_def] MRSL @{thm open_typedef_to_Quotient}
   632       | _ => 
   633         [typedef_thm, T_def] MRSL @{thm typedef_to_Quotient}
   634     val (rty, qty) = quot_thm_rty_qty quot_thm
   635     val qty_full_name = (fst o dest_Type) qty
   636     val qty_name = (Binding.name o Long_Name.base_name) qty_full_name
   637     fun qualify suffix = Binding.qualified true suffix qty_name
   638     val opt_reflp_thm = 
   639       case typedef_set of
   640         Const ("Orderings.top_class.top", _) => 
   641           SOME ((typedef_thm RS @{thm UNIV_typedef_to_equivp}) RS @{thm equivp_reflp2})
   642         | _ =>  NONE
   643     val dom_thm = get_Domainp_thm quot_thm
   644     val reflexivity_rule_attr = Attrib.internal (K Lifting_Info.add_reflexivity_rule_attribute)
   645 
   646     fun setup_transfer_rules_nonpar lthy =
   647       let
   648         val lthy =
   649           case opt_reflp_thm of
   650             SOME reflp_thm =>
   651               let 
   652                 val thms =
   653                   [("id_abs_transfer",@{thm Quotient_id_abs_transfer}),
   654                    ("bi_total",       @{thm Quotient_bi_total}       )]
   655               in
   656                 fold (fn (name, thm) => (snd oo Local_Theory.note) ((qualify name, [transfer_attr]), 
   657                     [[quot_thm, reflp_thm] MRSL thm])) thms lthy
   658               end
   659             | NONE =>
   660               lthy
   661               |> (snd oo Local_Theory.note) ((qualify "domain", [transfer_domain_attr]), [dom_thm])
   662         val thms = 
   663           [("rep_transfer", @{thm typedef_rep_transfer}),
   664            ("bi_unique",    @{thm typedef_bi_unique}   ),
   665            ("right_unique", @{thm typedef_right_unique}), 
   666            ("right_total",  @{thm typedef_right_total} )]
   667       in
   668         fold (fn (name, thm) => (snd oo Local_Theory.note) ((qualify name, [transfer_attr]), 
   669           [[typedef_thm, T_def] MRSL thm])) thms lthy
   670       end
   671 
   672     fun setup_transfer_rules_par lthy =
   673       let
   674         val pcrel_info = (the (get_pcrel_info lthy qty_full_name))
   675         val pcrel_def = #pcrel_def pcrel_info
   676 
   677         val lthy =
   678           case opt_reflp_thm of
   679             SOME reflp_thm =>
   680               let
   681                 val bi_total = ([quot_thm, reflp_thm] MRSL @{thm Quotient_bi_total})
   682                 val domain_thms = parametrize_total_domain bi_total pcrel_def lthy
   683                 val bi_total = parametrize_class_constraint lthy pcrel_def bi_total
   684                 val id_abs_transfer = generate_parametric_id lthy rty
   685                   (Lifting_Term.parametrize_transfer_rule lthy
   686                     ([quot_thm, reflp_thm] MRSL @{thm Quotient_id_abs_transfer}))
   687                 val thms = 
   688                   [("bi_total",       bi_total       ),
   689                    ("id_abs_transfer",id_abs_transfer)]              
   690               in
   691                 lthy
   692                 |> fold (fn (name, thm) => (snd oo Local_Theory.note) ((qualify name, [transfer_attr]), 
   693                      [thm])) thms
   694                 |> fold (fn (name, thm) => (snd oo Local_Theory.note) ((qualify name, [transfer_domain_attr]), 
   695                      [thm])) domain_thms
   696               end
   697             | NONE =>
   698               let
   699                 val thms = parametrize_domain dom_thm pcrel_info lthy
   700               in
   701                 fold (fn (name, thm) => (snd oo Local_Theory.note) ((qualify name, [transfer_domain_attr]), 
   702                   [thm])) thms lthy
   703               end
   704               
   705         val thms = 
   706           ("rep_transfer", generate_parametric_id lthy rty 
   707             (Lifting_Term.parametrize_transfer_rule lthy ([typedef_thm, T_def] MRSL @{thm typedef_rep_transfer})))
   708           ::
   709           (map_snd (fn thm => parametrize_class_constraint lthy pcrel_def ([typedef_thm, T_def] MRSL thm))
   710           [("bi_unique",    @{thm typedef_bi_unique} ),
   711            ("right_unique", @{thm typedef_right_unique}), 
   712            ("right_total",  @{thm typedef_right_total} )])
   713       in
   714         fold (fn (name, thm) => (snd oo Local_Theory.note) ((qualify name, [transfer_attr]), 
   715           [thm])) thms lthy
   716       end
   717 
   718     fun setup_transfer_rules lthy = 
   719       if is_some (get_pcrel_info lthy qty_full_name) then setup_transfer_rules_par lthy
   720                                                      else setup_transfer_rules_nonpar lthy
   721 
   722   in
   723     lthy
   724       |> (snd oo Local_Theory.note) ((Binding.prefix_name "Quotient_" qty_name, []), 
   725             [quot_thm])
   726       |> (snd oo Local_Theory.note) ((Binding.empty, [reflexivity_rule_attr]),
   727            [[typedef_thm, T_def] MRSL @{thm typedef_left_unique}])
   728       |> setup_lifting_infr gen_code quot_thm opt_reflp_thm
   729       |> setup_transfer_rules
   730   end
   731 
   732 fun setup_lifting_cmd gen_code xthm opt_reflp_xthm opt_par_xthm lthy =
   733   let 
   734     val input_thm = singleton (Attrib.eval_thms lthy) xthm
   735     val input_term = (HOLogic.dest_Trueprop o prop_of) input_thm
   736       handle TERM _ => error "Unsupported type of a theorem. Only Quotient or type_definition are supported."
   737 
   738     fun sanity_check_reflp_thm reflp_thm = 
   739       let
   740         val reflp_tm = (HOLogic.dest_Trueprop o prop_of) reflp_thm
   741           handle TERM _ => error "Invalid form of the reflexivity theorem. Use \"reflp R\"."
   742       in
   743         case reflp_tm of
   744           Const (@{const_name reflp}, _) $ _ => ()
   745           | _ => error "Invalid form of the reflexivity theorem. Use \"reflp R\"."
   746       end
   747 
   748     fun setup_quotient () = 
   749       let
   750         val opt_reflp_thm = Option.map (singleton (Attrib.eval_thms lthy)) opt_reflp_xthm
   751         val _ = if is_some opt_reflp_thm then sanity_check_reflp_thm (the opt_reflp_thm) else ()
   752         val opt_par_thm = Option.map (singleton (Attrib.eval_thms lthy)) opt_par_xthm
   753       in
   754         setup_by_quotient gen_code input_thm opt_reflp_thm opt_par_thm lthy
   755       end
   756       
   757 
   758     fun setup_typedef () = 
   759       case opt_reflp_xthm of
   760         SOME _ => error "The reflexivity theorem cannot be specified if the type_definition theorem is used."
   761         | NONE => (
   762           case opt_par_xthm of
   763             SOME _ => error "The parametricity theorem cannot be specified if the type_definition theorem is used."
   764             | NONE => setup_by_typedef_thm gen_code input_thm lthy
   765         )
   766   in
   767     case input_term of
   768       (Const (@{const_name Quotient}, _) $ _ $ _ $ _ $ _) => setup_quotient ()
   769       | (Const (@{const_name type_definition}, _) $ _ $ _ $ _) => setup_typedef ()
   770       | _ => error "Unsupported type of a theorem. Only Quotient or type_definition are supported."
   771   end
   772 
   773 val opt_gen_code =
   774   Scan.optional (@{keyword "("} |-- Parse.!!! ((Parse.reserved "no_code" >> K false) --| @{keyword ")"})) true
   775 
   776 val _ = 
   777   Outer_Syntax.local_theory @{command_spec "setup_lifting"}
   778     "setup lifting infrastructure" 
   779       (opt_gen_code -- Parse_Spec.xthm -- Scan.option Parse_Spec.xthm 
   780       -- Scan.option (@{keyword "parametric"} |-- Parse.!!! Parse_Spec.xthm) >> 
   781         (fn (((gen_code, xthm), opt_reflp_xthm), opt_par_xthm) => 
   782           setup_lifting_cmd gen_code xthm opt_reflp_xthm opt_par_xthm))
   783 
   784 (* restoring lifting infrastructure *)
   785 
   786 local
   787   exception PCR_ERROR of Pretty.T list
   788 in
   789 
   790 fun lifting_restore_sanity_check ctxt (qinfo:Lifting_Info.quotient) =
   791   let
   792     val quot_thm = (#quot_thm qinfo)
   793     val _ = quot_thm_sanity_check ctxt quot_thm
   794     val pcr_info_err =
   795       (case #pcr_info qinfo of
   796         SOME pcr => 
   797           let
   798             val pcrel_def = #pcrel_def pcr
   799             val pcr_cr_eq = #pcr_cr_eq pcr
   800             val (def_lhs, _) = Logic.dest_equals (prop_of pcrel_def)
   801               handle TERM _ => raise PCR_ERROR [Pretty.block 
   802                     [Pretty.str "The pcr definiton theorem is not a plain meta equation:",
   803                     Pretty.brk 1,
   804                     Display.pretty_thm ctxt pcrel_def]]
   805             val pcr_const_def = head_of def_lhs
   806             val (eq_lhs, eq_rhs) = HOLogic.dest_eq (HOLogic.dest_Trueprop (prop_of pcr_cr_eq))
   807               handle TERM _ => raise PCR_ERROR [Pretty.block 
   808                     [Pretty.str "The pcr_cr equation theorem is not a plain equation:",
   809                     Pretty.brk 1,
   810                     Display.pretty_thm ctxt pcr_cr_eq]]
   811             val (pcr_const_eq, eqs) = strip_comb eq_lhs
   812             fun is_eq (Const ("HOL.eq", _)) = true
   813               | is_eq _ = false
   814             fun eq_Const (Const (name1, _)) (Const (name2, _)) = (name1 = name2)
   815               | eq_Const _ _ = false
   816             val all_eqs = if not (forall is_eq eqs) then 
   817               [Pretty.block
   818                     [Pretty.str "Arguments of the lhs of the pcr_cr equation theorem are not only equalities:",
   819                     Pretty.brk 1,
   820                     Display.pretty_thm ctxt pcr_cr_eq]]
   821               else []
   822             val pcr_consts_not_equal = if not (eq_Const pcr_const_def pcr_const_eq) then
   823               [Pretty.block
   824                     [Pretty.str "Parametrized correspondence relation constants in pcr_def and pcr_cr_eq are not equal:",
   825                     Pretty.brk 1,
   826                     Syntax.pretty_term ctxt pcr_const_def,
   827                     Pretty.brk 1,
   828                     Pretty.str "vs.",
   829                     Pretty.brk 1,
   830                     Syntax.pretty_term ctxt pcr_const_eq]]
   831               else []
   832             val crel = quot_thm_crel quot_thm
   833             val cr_consts_not_equal = if not (eq_Const crel eq_rhs) then
   834               [Pretty.block
   835                     [Pretty.str "Correspondence relation constants in the Quotient theorem and pcr_cr_eq are not equal:",
   836                     Pretty.brk 1,
   837                     Syntax.pretty_term ctxt crel,
   838                     Pretty.brk 1,
   839                     Pretty.str "vs.",
   840                     Pretty.brk 1,
   841                     Syntax.pretty_term ctxt eq_rhs]]
   842               else []
   843           in
   844             all_eqs @ pcr_consts_not_equal @ cr_consts_not_equal
   845           end
   846         | NONE => [])
   847     val errs = pcr_info_err
   848   in
   849     if null errs then () else raise PCR_ERROR errs
   850   end
   851   handle PCR_ERROR errs => error (cat_lines (["Sanity check failed:"] 
   852                                             @ (map (Pretty.string_of o Pretty.item o single) errs)))
   853 end
   854 
   855 fun lifting_restore qinfo ctxt =
   856   let
   857     val _ = lifting_restore_sanity_check (Context.proof_of ctxt) qinfo
   858     val (_, qty) = quot_thm_rty_qty (#quot_thm qinfo)
   859     val qty_full_name = (fst o dest_Type) qty
   860     val stored_qinfo = Lifting_Info.lookup_quotients (Context.proof_of ctxt) qty_full_name
   861   in
   862     if is_some (stored_qinfo) andalso not (Lifting_Info.quotient_eq (qinfo, (the stored_qinfo)))
   863       then error (Pretty.string_of 
   864         (Pretty.block
   865           [Pretty.str "Lifting is already setup for the type",
   866            Pretty.brk 1,
   867            Pretty.quote (Syntax.pretty_typ (Context.proof_of ctxt) qty)]))
   868       else Lifting_Info.update_quotients qty_full_name qinfo ctxt
   869   end
   870 
   871 val parse_opt_pcr =
   872   Scan.optional (Attrib.thm -- Attrib.thm >> 
   873     (fn (pcrel_def, pcr_cr_eq) => SOME {pcrel_def = pcrel_def, pcr_cr_eq = pcr_cr_eq})) NONE
   874 
   875 val lifting_restore_attribute_setup =
   876   Attrib.setup @{binding lifting_restore}
   877     ((Attrib.thm -- parse_opt_pcr) >>
   878       (fn (quot_thm, opt_pcr) =>
   879         let val qinfo = { quot_thm = quot_thm, pcr_info = opt_pcr}
   880         in Thm.declaration_attribute (K (lifting_restore qinfo)) end))
   881     "restoring lifting infrastructure"
   882 
   883 val _ = Theory.setup lifting_restore_attribute_setup 
   884 
   885 fun lifting_restore_internal bundle_name ctxt = 
   886   let 
   887     val restore_info = Lifting_Info.lookup_restore_data (Context.proof_of ctxt) bundle_name
   888   in
   889     case restore_info of
   890       SOME restore_info =>
   891         ctxt 
   892         |> lifting_restore (#quotient restore_info)
   893         |> fold_rev Transfer.transfer_raw_add (Item_Net.content (#transfer_rules restore_info))
   894       | NONE => ctxt
   895   end
   896 
   897 val lifting_restore_internal_attribute_setup =
   898   Attrib.setup @{binding lifting_restore_internal}
   899      (Scan.lift Args.name >> (fn name => Thm.declaration_attribute (K (lifting_restore_internal name))))
   900     "restoring lifting infrastructure; internal attribute; not meant to be used directly by regular users"
   901 
   902 val _ = Theory.setup lifting_restore_internal_attribute_setup 
   903 
   904 (* lifting_forget *)
   905 
   906 val monotonicity_names = [@{const_name right_unique}, @{const_name left_unique}, @{const_name right_total},
   907   @{const_name left_total}, @{const_name bi_unique}, @{const_name bi_total}]
   908 
   909 fun fold_transfer_rel f (Const (@{const_name "Transfer.Rel"}, _) $ rel $ _ $ _) = f rel
   910   | fold_transfer_rel f (Const (@{const_name "HOL.eq"}, _) $ 
   911     (Const (@{const_name Domainp}, _) $ rel) $ _) = f rel
   912   | fold_transfer_rel f (Const (name, _) $ rel) = 
   913     if member op= monotonicity_names name then f rel else f @{term undefined}
   914   | fold_transfer_rel f _ = f @{term undefined}
   915 
   916 fun filter_transfer_rules_by_rel transfer_rel transfer_rules =
   917   let
   918     val transfer_rel_name = transfer_rel |> dest_Const |> fst;
   919     fun has_transfer_rel thm = 
   920       let
   921         val concl = thm |> concl_of |> HOLogic.dest_Trueprop
   922       in
   923         member op= (fold_transfer_rel (fn tm => Term.add_const_names tm []) concl) transfer_rel_name
   924       end
   925       handle TERM _ => false
   926   in
   927     filter has_transfer_rel transfer_rules
   928   end
   929 
   930 type restore_data = {quotient : Lifting_Info.quotient, transfer_rules: thm Item_Net.T}
   931 
   932 fun get_transfer_rel (qinfo : Lifting_Info.quotient) =
   933   let
   934     fun get_pcrel pcr_def = pcr_def |> concl_of |> Logic.dest_equals |> fst |> head_of
   935   in
   936     if is_some (#pcr_info qinfo) 
   937       then get_pcrel (#pcrel_def (the (#pcr_info qinfo)))
   938       else quot_thm_crel (#quot_thm qinfo)
   939   end
   940 
   941 fun pointer_of_bundle_name bundle_name ctxt =
   942   let
   943     val bundle_name = Bundle.check ctxt bundle_name
   944     val bundle = Bundle.the_bundle ctxt bundle_name
   945   in
   946     case bundle of
   947       [(_, [arg_src])] => 
   948         (let
   949           val ((_, tokens), _) = Args.dest_src arg_src
   950         in
   951           (fst (Args.name tokens))
   952           handle _ => error "The provided bundle is not a lifting bundle."
   953         end)
   954       | _ => error "The provided bundle is not a lifting bundle."
   955   end
   956 
   957 fun lifting_forget pointer lthy =
   958   let
   959     fun get_transfer_rules_to_delete qinfo ctxt =
   960       let
   961         val transfer_rel = get_transfer_rel qinfo
   962       in
   963          filter_transfer_rules_by_rel transfer_rel (Transfer.get_transfer_raw ctxt)
   964       end
   965   in
   966     case Lifting_Info.lookup_restore_data lthy pointer of
   967       SOME restore_info =>
   968         let
   969           val qinfo = #quotient restore_info
   970           val quot_thm = #quot_thm qinfo
   971           val transfer_rules = get_transfer_rules_to_delete qinfo lthy
   972         in
   973           Local_Theory.declaration {syntax = false, pervasive = true}
   974             (K (fold (Transfer.transfer_raw_del) transfer_rules #> Lifting_Info.delete_quotients quot_thm))
   975             lthy
   976         end
   977       | NONE => error "The lifting bundle refers to non-existent restore data."
   978     end
   979     
   980 
   981 fun lifting_forget_cmd bundle_name lthy = 
   982   lifting_forget (pointer_of_bundle_name bundle_name lthy) lthy
   983 
   984 
   985 val _ =
   986   Outer_Syntax.local_theory @{command_spec "lifting_forget"} 
   987     "unsetup Lifting and Transfer for the given lifting bundle"
   988     (Parse.position Parse.xname >> (lifting_forget_cmd))
   989 
   990 (* lifting_update *)
   991 
   992 fun update_transfer_rules pointer lthy =
   993   let
   994     fun new_transfer_rules ({ quotient = qinfo, ... }:Lifting_Info.restore_data) lthy =
   995       let
   996         val transfer_rel = get_transfer_rel qinfo
   997         val transfer_rules = filter_transfer_rules_by_rel transfer_rel (Transfer.get_transfer_raw lthy)
   998       in
   999         fn phi => fold_rev 
  1000           (Item_Net.update o Morphism.thm phi) transfer_rules Thm.full_rules
  1001       end
  1002   in
  1003     case Lifting_Info.lookup_restore_data lthy pointer of
  1004       SOME refresh_data => 
  1005         Local_Theory.declaration {syntax = false, pervasive = true}
  1006           (fn phi => Lifting_Info.add_transfer_rules_in_restore_data pointer 
  1007             (new_transfer_rules refresh_data lthy phi)) lthy
  1008       | NONE => error "The lifting bundle refers to non-existent restore data."
  1009   end
  1010 
  1011 fun lifting_update_cmd bundle_name lthy = 
  1012   update_transfer_rules (pointer_of_bundle_name bundle_name lthy) lthy
  1013 
  1014 val _ =
  1015   Outer_Syntax.local_theory @{command_spec "lifting_update"}
  1016     "add newly introduced transfer rules to a bundle storing the state of Lifting and Transfer"
  1017     (Parse.position Parse.xname >> lifting_update_cmd)
  1018 
  1019 end