src/HOL/Tools/BNF/bnf_fp_rec_sugar_transfer.ML
author wenzelm
Fri, 06 Mar 2015 15:58:56 +0100
changeset 59621 291934bac95e
parent 59580 cbc38731d42f
child 60784 4f590c08fd5d
permissions -rw-r--r--
Thm.cterm_of and Thm.ctyp_of operate on local context;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
59275
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
     1
(*  Title:      HOL/Tools/BNF/bnf_fp_rec_sugar_transfer.ML
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
     2
    Author:     Martin Desharnais, TU Muenchen
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
     3
    Copyright   2014
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
     4
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
     5
Parametricity of primitively (co)recursive functions.
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
     6
*)
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
     7
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
     8
signature BNF_FP_REC_SUGAR_TRANSFER =
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
     9
sig
59281
1b4dc8a9f7d9 added plugins syntax to prim(co)rec
blanchet
parents: 59276
diff changeset
    10
  val lfp_rec_sugar_transfer_interpretation: BNF_FP_Rec_Sugar_Util.fp_rec_sugar -> Proof.context ->
59276
blanchet
parents: 59275
diff changeset
    11
    Proof.context
59281
1b4dc8a9f7d9 added plugins syntax to prim(co)rec
blanchet
parents: 59276
diff changeset
    12
  val gfp_rec_sugar_transfer_interpretation: BNF_FP_Rec_Sugar_Util.fp_rec_sugar -> Proof.context ->
59276
blanchet
parents: 59275
diff changeset
    13
    Proof.context
59275
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    14
end;
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    15
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    16
structure BNF_FP_Rec_Sugar_Transfer : BNF_FP_REC_SUGAR_TRANSFER =
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    17
struct
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    18
59276
blanchet
parents: 59275
diff changeset
    19
open Ctr_Sugar_Util
blanchet
parents: 59275
diff changeset
    20
open Ctr_Sugar_Tactics
59297
blanchet
parents: 59281
diff changeset
    21
open BNF_Util
59275
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    22
open BNF_Def
59276
blanchet
parents: 59275
diff changeset
    23
open BNF_FP_Util
59275
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    24
open BNF_FP_Def_Sugar
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    25
open BNF_FP_Rec_Sugar_Util
59281
1b4dc8a9f7d9 added plugins syntax to prim(co)rec
blanchet
parents: 59276
diff changeset
    26
open BNF_LFP_Rec_Sugar
59275
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    27
59276
blanchet
parents: 59275
diff changeset
    28
val transferN = "transfer";
59275
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    29
59281
1b4dc8a9f7d9 added plugins syntax to prim(co)rec
blanchet
parents: 59276
diff changeset
    30
fun mk_lfp_rec_sugar_transfer_tac ctxt def =
59297
blanchet
parents: 59281
diff changeset
    31
  unfold_thms_tac ctxt [def] THEN HEADGOAL (Transfer.transfer_prover_tac ctxt);
59275
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    32
59297
blanchet
parents: 59281
diff changeset
    33
fun mk_gfp_rec_sugar_transfer_tac ctxt f_def corec_def type_definitions dtor_corec_transfers
blanchet
parents: 59281
diff changeset
    34
    rel_pre_defs disc_eq_cases cases case_distribs case_congs =
59275
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    35
  let
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    36
    fun instantiate_with_lambda thm =
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    37
      let
59297
blanchet
parents: 59281
diff changeset
    38
        val prop as @{const Trueprop} $ (Const (@{const_name HOL.eq}, _) $ (Var (_, fT) $ _) $ _) =
blanchet
parents: 59281
diff changeset
    39
          Thm.prop_of thm;
59275
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    40
        val T = range_type fT;
59276
blanchet
parents: 59275
diff changeset
    41
        val j = Term.maxidx_of_term prop + 1;
blanchet
parents: 59275
diff changeset
    42
        val cond = Var (("x", j), HOLogic.boolT);
blanchet
parents: 59275
diff changeset
    43
        val then_branch = Var (("t", j), T);
blanchet
parents: 59275
diff changeset
    44
        val else_branch = Var (("e", j), T);
59297
blanchet
parents: 59281
diff changeset
    45
        val lam = Term.lambda cond (mk_If cond then_branch else_branch);
59275
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    46
      in
59621
291934bac95e Thm.cterm_of and Thm.ctyp_of operate on local context;
wenzelm
parents: 59580
diff changeset
    47
        cterm_instantiate_pos [SOME (Thm.cterm_of ctxt lam)] thm
59275
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    48
      end;
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    49
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    50
    val transfer_rules =
59297
blanchet
parents: 59281
diff changeset
    51
      @{thm Abs_transfer[OF type_definition_id_bnf_UNIV type_definition_id_bnf_UNIV]} ::
59275
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    52
      map (fn thm => @{thm Abs_transfer} OF [thm, thm]) type_definitions @
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    53
      map (Local_Defs.unfold ctxt rel_pre_defs) dtor_corec_transfers;
59276
blanchet
parents: 59275
diff changeset
    54
    val add_transfer_rule = Thm.attribute_declaration Transfer.transfer_add;
blanchet
parents: 59275
diff changeset
    55
    val ctxt' = Context.proof_map (fold add_transfer_rule transfer_rules) ctxt;
59275
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    56
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    57
    val case_distribs = map instantiate_with_lambda case_distribs;
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    58
    val simps = case_distribs @ disc_eq_cases @ cases @ @{thms if_True if_False};
59297
blanchet
parents: 59281
diff changeset
    59
    val ctxt'' = put_simpset (simpset_of (ss_only simps ctxt)) ctxt';
59275
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    60
  in
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    61
    unfold_thms_tac ctxt ([f_def, corec_def] @ @{thms split_beta if_conn}) THEN
59297
blanchet
parents: 59281
diff changeset
    62
    HEADGOAL (simp_tac (fold Simplifier.add_cong case_congs ctxt'')) THEN
blanchet
parents: 59281
diff changeset
    63
    HEADGOAL (Transfer.transfer_prover_tac ctxt')
59275
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    64
  end;
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    65
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    66
fun massage_simple_notes base =
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    67
  filter_out (null o #2)
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    68
  #> map (fn (thmN, thms, f_attrs) =>
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    69
    ((Binding.qualify true base (Binding.name thmN), []),
59297
blanchet
parents: 59281
diff changeset
    70
     map_index (fn (kk, thm) => ([thm], f_attrs kk)) thms));
59275
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    71
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    72
fun fp_sugar_of_bnf ctxt = fp_sugar_of ctxt o (fn Type (s, _) => s) o T_of_bnf;
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    73
59297
blanchet
parents: 59281
diff changeset
    74
fun bnf_depth_first_traverse ctxt f T =
59276
blanchet
parents: 59275
diff changeset
    75
  (case T of
59297
blanchet
parents: 59281
diff changeset
    76
    Type (s, Ts) =>
59275
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    77
    (case bnf_of ctxt s of
59297
blanchet
parents: 59281
diff changeset
    78
      NONE => I
blanchet
parents: 59281
diff changeset
    79
    | SOME bnf => fold (bnf_depth_first_traverse ctxt f) Ts o f bnf)
blanchet
parents: 59281
diff changeset
    80
  | _ => I);
59275
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    81
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    82
fun mk_goal lthy f =
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    83
  let
59276
blanchet
parents: 59275
diff changeset
    84
    val skematic_Ts = Term.add_tvarsT (fastype_of f) [];
59275
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    85
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    86
    val ((As, Bs), names_lthy) = lthy
59297
blanchet
parents: 59281
diff changeset
    87
      |> mk_TFrees' (map snd skematic_Ts)
blanchet
parents: 59281
diff changeset
    88
      ||>> mk_TFrees' (map snd skematic_Ts);
59275
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    89
59297
blanchet
parents: 59281
diff changeset
    90
    val (Rs, names_lthy) = mk_Frees "R" (map2 mk_pred2T As Bs) names_lthy;
59275
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    91
59276
blanchet
parents: 59275
diff changeset
    92
    val fA = Term.subst_TVars (map fst skematic_Ts ~~ As) f;
blanchet
parents: 59275
diff changeset
    93
    val fB = Term.subst_TVars (map fst skematic_Ts ~~ Bs) f;
59275
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    94
  in
59297
blanchet
parents: 59281
diff changeset
    95
    (mk_parametricity_goal lthy Rs fA fB, names_lthy)
59275
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    96
  end;
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
    97
59297
blanchet
parents: 59281
diff changeset
    98
fun fp_rec_sugar_transfer_interpretation prove {transfers, fun_names, funs, fun_defs, fpTs} =
blanchet
parents: 59281
diff changeset
    99
  fold_index (fn (kk, (((transfer, fun_name), funx), fun_def)) => fn lthy =>
blanchet
parents: 59281
diff changeset
   100
      if transfer then
blanchet
parents: 59281
diff changeset
   101
        (case try (map the) (map (fn Type (s, _) => bnf_of lthy s | _ => NONE) fpTs) of
blanchet
parents: 59281
diff changeset
   102
          NONE => error "No transfer rule possible"
blanchet
parents: 59281
diff changeset
   103
        | SOME bnfs =>
blanchet
parents: 59281
diff changeset
   104
          (case try (prove kk bnfs funx fun_def) lthy of
blanchet
parents: 59281
diff changeset
   105
            NONE => error "Failed to prove transfer rule"
blanchet
parents: 59281
diff changeset
   106
          | SOME thm =>
blanchet
parents: 59281
diff changeset
   107
            let
blanchet
parents: 59281
diff changeset
   108
              val notes = [(transferN, [thm], K @{attributes [transfer_rule]})]
blanchet
parents: 59281
diff changeset
   109
                |> massage_simple_notes fun_name;
blanchet
parents: 59281
diff changeset
   110
            in
blanchet
parents: 59281
diff changeset
   111
              snd (Local_Theory.notes notes lthy)
blanchet
parents: 59281
diff changeset
   112
            end))
59275
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
   113
      else
59297
blanchet
parents: 59281
diff changeset
   114
        lthy)
blanchet
parents: 59281
diff changeset
   115
    (transfers ~~ fun_names ~~ funs ~~ fun_defs);
59275
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
   116
59281
1b4dc8a9f7d9 added plugins syntax to prim(co)rec
blanchet
parents: 59276
diff changeset
   117
val lfp_rec_sugar_transfer_interpretation = fp_rec_sugar_transfer_interpretation
59276
blanchet
parents: 59275
diff changeset
   118
  (fn _ => fn _ => fn f => fn def => fn lthy =>
blanchet
parents: 59275
diff changeset
   119
     let val (goal, names_lthy) = mk_goal lthy f in
59275
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
   120
       Goal.prove lthy [] [] goal (fn {context = ctxt, prems = _} =>
59281
1b4dc8a9f7d9 added plugins syntax to prim(co)rec
blanchet
parents: 59276
diff changeset
   121
         mk_lfp_rec_sugar_transfer_tac ctxt def)
59275
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
   122
       |> singleton (Proof_Context.export names_lthy lthy)
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
   123
       |> Thm.close_derivation
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
   124
     end);
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
   125
59281
1b4dc8a9f7d9 added plugins syntax to prim(co)rec
blanchet
parents: 59276
diff changeset
   126
val gfp_rec_sugar_transfer_interpretation = fp_rec_sugar_transfer_interpretation
59297
blanchet
parents: 59281
diff changeset
   127
  (fn kk => fn bnfs => fn f => fn def => fn lthy =>
59275
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
   128
     let
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
   129
       val fp_sugars = map (the o fp_sugar_of_bnf lthy) bnfs;
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
   130
       val (goal, names_lthy) = mk_goal lthy f;
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
   131
       val (disc_eq_cases, case_thms, case_distribs, case_congs) =
59297
blanchet
parents: 59281
diff changeset
   132
         bnf_depth_first_traverse lthy (fn bnf =>
blanchet
parents: 59281
diff changeset
   133
             (case fp_sugar_of_bnf lthy bnf of
blanchet
parents: 59281
diff changeset
   134
               NONE => I
blanchet
parents: 59281
diff changeset
   135
             | SOME {fp_ctr_sugar = {ctr_sugar = {disc_eq_cases, case_thms, case_distribs,
blanchet
parents: 59281
diff changeset
   136
                 case_cong, ...}, ...}, ...} =>
blanchet
parents: 59281
diff changeset
   137
               (fn (disc_eq_cases0, case_thms0, case_distribs0, case_congs0) =>
blanchet
parents: 59281
diff changeset
   138
                  (union Thm.eq_thm disc_eq_cases disc_eq_cases0,
blanchet
parents: 59281
diff changeset
   139
                   union Thm.eq_thm case_thms case_thms0,
blanchet
parents: 59281
diff changeset
   140
                   union Thm.eq_thm case_distribs case_distribs0,
blanchet
parents: 59281
diff changeset
   141
                   insert Thm.eq_thm case_cong case_congs0))))
blanchet
parents: 59281
diff changeset
   142
           (fastype_of f) ([], [], [], []);
59275
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
   143
     in
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
   144
       Goal.prove lthy [] [] goal (fn {context = ctxt, prems = _} =>
59297
blanchet
parents: 59281
diff changeset
   145
         mk_gfp_rec_sugar_transfer_tac ctxt def
blanchet
parents: 59281
diff changeset
   146
         (#co_rec_def (#fp_co_induct_sugar (nth fp_sugars kk)))
59275
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
   147
         (map (#type_definition o #absT_info) fp_sugars)
59276
blanchet
parents: 59275
diff changeset
   148
         (maps (#xtor_co_rec_transfers o #fp_res) fp_sugars)
59275
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
   149
         (map (rel_def_of_bnf o #pre_bnf) fp_sugars)
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
   150
         disc_eq_cases case_thms case_distribs case_congs)
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
   151
       |> singleton (Proof_Context.export names_lthy lthy)
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
   152
       |> Thm.close_derivation
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
   153
     end);
77cd4992edcd Add plugin to generate transfer theorem for primrec and primcorec
desharna
parents:
diff changeset
   154
59281
1b4dc8a9f7d9 added plugins syntax to prim(co)rec
blanchet
parents: 59276
diff changeset
   155
val _ = Theory.setup (lfp_rec_sugar_interpretation Transfer_BNF.transfer_plugin
1b4dc8a9f7d9 added plugins syntax to prim(co)rec
blanchet
parents: 59276
diff changeset
   156
  lfp_rec_sugar_transfer_interpretation);
59276
blanchet
parents: 59275
diff changeset
   157
blanchet
parents: 59275
diff changeset
   158
end;