src/HOL/Nominal/nominal_package.ML
changeset 20376 53b31f7c1d87
parent 20267 1154363129be
child 20397 243293620225
equal deleted inserted replaced
20375:e91be828ce4e 20376:53b31f7c1d87
   135 fun projections rule =
   135 fun projections rule =
   136   ProjectRule.projections (ProofContext.init (Thm.theory_of_thm rule)) rule
   136   ProjectRule.projections (ProofContext.init (Thm.theory_of_thm rule)) rule
   137   |> map (standard #> RuleCases.save rule);
   137   |> map (standard #> RuleCases.save rule);
   138 
   138 
   139 val supp_prod = thm "supp_prod";
   139 val supp_prod = thm "supp_prod";
       
   140 val fresh_prod = thm "fresh_prod";
       
   141 val supports_fresh = thm "supports_fresh";
       
   142 val supports_def = thm "Nominal.op supports_def";
       
   143 val fresh_def = thm "fresh_def";
       
   144 val supp_def = thm "supp_def";
       
   145 val rev_simps = thms "rev.simps";
       
   146 val app_simps = thms "op @.simps";
   140 
   147 
   141 fun gen_add_nominal_datatype prep_typ err flat_names new_type_names dts thy =
   148 fun gen_add_nominal_datatype prep_typ err flat_names new_type_names dts thy =
   142   let
   149   let
   143     (* this theory is used just for parsing *)
   150     (* this theory is used just for parsing *)
   144   
   151   
   869     (** prove injectivity of constructors **)
   876     (** prove injectivity of constructors **)
   870 
   877 
   871     val rep_inject_thms' = map (fn th => th RS sym) rep_inject_thms;
   878     val rep_inject_thms' = map (fn th => th RS sym) rep_inject_thms;
   872     val alpha = PureThy.get_thms thy8 (Name "alpha");
   879     val alpha = PureThy.get_thms thy8 (Name "alpha");
   873     val abs_fresh = PureThy.get_thms thy8 (Name "abs_fresh");
   880     val abs_fresh = PureThy.get_thms thy8 (Name "abs_fresh");
   874     val fresh_def = PureThy.get_thm thy8 (Name "fresh_def");
       
   875     val supp_def = PureThy.get_thm thy8 (Name "supp_def");
       
   876 
   881 
   877     val inject_thms = map (fn (((i, (_, _, constrs)), tname), constr_rep_thms) =>
   882     val inject_thms = map (fn (((i, (_, _, constrs)), tname), constr_rep_thms) =>
   878       let val T = nth_dtyp' i
   883       let val T = nth_dtyp' i
   879       in List.mapPartial (fn ((cname, dts), constr_rep_thm) =>
   884       in List.mapPartial (fn ((cname, dts), constr_rep_thm) =>
   880         if null dts then NONE else SOME
   885         if null dts then NONE else SOME
   913                   expand_fun_eq :: rep_inject_thms @ perm_rep_perm_thms)) 1)])
   918                   expand_fun_eq :: rep_inject_thms @ perm_rep_perm_thms)) 1)])
   914         end) (constrs ~~ constr_rep_thms)
   919         end) (constrs ~~ constr_rep_thms)
   915       end) (List.take (pdescr, length new_type_names) ~~ new_type_names ~~ constr_rep_thmss);
   920       end) (List.take (pdescr, length new_type_names) ~~ new_type_names ~~ constr_rep_thmss);
   916 
   921 
   917     (** equations for support and freshness **)
   922     (** equations for support and freshness **)
   918 
       
   919     val Un_assoc = PureThy.get_thm thy8 (Name "Un_assoc");
       
   920     val de_Morgan_conj = PureThy.get_thm thy8 (Name "de_Morgan_conj");
       
   921     val Collect_disj_eq = PureThy.get_thm thy8 (Name "Collect_disj_eq");
       
   922     val finite_Un = PureThy.get_thm thy8 (Name "finite_Un");
       
   923 
   923 
   924     val (supp_thms, fresh_thms) = ListPair.unzip (map ListPair.unzip
   924     val (supp_thms, fresh_thms) = ListPair.unzip (map ListPair.unzip
   925       (map (fn ((((i, (_, _, constrs)), tname), inject_thms'), perm_thms') =>
   925       (map (fn ((((i, (_, _, constrs)), tname), inject_thms'), perm_thms') =>
   926       let val T = nth_dtyp' i
   926       let val T = nth_dtyp' i
   927       in List.concat (map (fn (cname, dts) => map (fn atom =>
   927       in List.concat (map (fn (cname, dts) => map (fn atom =>
  1409           mk_fresh2 [] frees';
  1409           mk_fresh2 [] frees';
  1410         val prems4 = map (fn ((i, _), y) =>
  1410         val prems4 = map (fn ((i, _), y) =>
  1411           HOLogic.mk_Trueprop (List.nth (rec_preds, i) $ Free y)) (recs ~~ frees'');
  1411           HOLogic.mk_Trueprop (List.nth (rec_preds, i) $ Free y)) (recs ~~ frees'');
  1412         val prems5 = mk_fresh3 (recs ~~ frees'') frees';
  1412         val prems5 = mk_fresh3 (recs ~~ frees'') frees';
  1413         val result = list_comb (List.nth (rec_fns, l), map Free (frees @ frees''));
  1413         val result = list_comb (List.nth (rec_fns, l), map Free (frees @ frees''));
  1414         val rec_freshs = map (fn p as (_, T) =>
  1414         val result_freshs = map (fn p as (_, T) =>
  1415           Const ("Nominal.fresh", T --> fastype_of result --> HOLogic.boolT) $
  1415           Const ("Nominal.fresh", T --> fastype_of result --> HOLogic.boolT) $
  1416             Free p $ result) (List.concat (map (fst o snd) recs));
  1416             Free p $ result) (List.concat (map fst frees'));
  1417         val P = HOLogic.mk_Trueprop (p $ result)
  1417         val P = HOLogic.mk_Trueprop (p $ result)
  1418       in
  1418       in
  1419         (rec_intr_ts @ [Logic.list_implies (List.concat prems2 @ prems3 @ prems1,
  1419         (rec_intr_ts @ [Logic.list_implies (List.concat prems2 @ prems3 @ prems1,
  1420            HOLogic.mk_Trueprop (HOLogic.mk_mem
  1420            HOLogic.mk_Trueprop (HOLogic.mk_mem
  1421              (HOLogic.mk_prod (list_comb (Const (cname, Ts ---> T), map Free frees),
  1421              (HOLogic.mk_prod (list_comb (Const (cname, Ts ---> T), map Free frees),
  1422                result), rec_set)))],
  1422                result), rec_set)))],
  1423          rec_prems @ [list_all_free (frees @ frees'', Logic.list_implies (prems4, P))],
  1423          rec_prems @ [list_all_free (frees @ frees'', Logic.list_implies (prems4, P))],
  1424          if null rec_freshs then rec_prems'
  1424          if null result_freshs then rec_prems'
  1425          else rec_prems' @ [list_all_free (frees @ frees'',
  1425          else rec_prems' @ [list_all_free (frees @ frees'',
  1426            Logic.list_implies (List.nth (prems2, l) @ prems3 @ prems5 @ [P],
  1426            Logic.list_implies (List.nth (prems2, l) @ prems3 @ prems5 @ [P],
  1427              HOLogic.mk_Trueprop (foldr1 HOLogic.mk_conj rec_freshs)))],
  1427              HOLogic.mk_Trueprop (foldr1 HOLogic.mk_conj result_freshs)))],
  1428          l + 1)
  1428          l + 1)
  1429       end;
  1429       end;
  1430 
  1430 
  1431     val (rec_intr_ts, rec_prems, rec_prems', _) =
  1431     val (rec_intr_ts, rec_prems, rec_prems', _) =
  1432       Library.foldl (fn (x, ((((d, d'), T), p), rec_set)) =>
  1432       Library.foldl (fn (x, ((((d, d'), T), p), rec_set)) =>
  1500                  end) (recTs ~~ rec_result_Ts ~~ rec_sets ~~ (1 upto length recTs)))))
  1500                  end) (recTs ~~ rec_result_Ts ~~ rec_sets ~~ (1 upto length recTs)))))
  1501             (fn fins => (rtac rec_induct THEN_ALL_NEW cut_facts_tac fins) 1 THEN REPEAT
  1501             (fn fins => (rtac rec_induct THEN_ALL_NEW cut_facts_tac fins) 1 THEN REPEAT
  1502                (NominalPermeq.finite_guess_tac (HOL_ss addsimps [fs_name]) 1))))
  1502                (NominalPermeq.finite_guess_tac (HOL_ss addsimps [fs_name]) 1))))
  1503       end) dt_atomTs;
  1503       end) dt_atomTs;
  1504 
  1504 
  1505     (** uniqueness **)
  1505     (** freshness **)
  1506 
  1506 
  1507     val fresh_prems = List.concat (map (fn aT =>
  1507     val perm_fresh_fresh = PureThy.get_thms thy11 (Name "perm_fresh_fresh");
       
  1508     val perm_swap = PureThy.get_thms thy11 (Name "perm_swap");
       
  1509 
       
  1510     fun perm_of_pair (x, y) =
       
  1511       let
       
  1512         val T = fastype_of x;
       
  1513         val pT = mk_permT T
       
  1514       in Const ("List.list.Cons", HOLogic.mk_prodT (T, T) --> pT --> pT) $
       
  1515         HOLogic.mk_prod (x, y) $ Const ("List.list.Nil", pT)
       
  1516       end;
       
  1517 
       
  1518     val finite_premss = map (fn aT =>
  1508       map (fn (f, T) => HOLogic.mk_Trueprop (HOLogic.mk_mem
  1519       map (fn (f, T) => HOLogic.mk_Trueprop (HOLogic.mk_mem
  1509         (Const ("Nominal.supp", T --> HOLogic.mk_setT aT) $ f,
  1520         (Const ("Nominal.supp", T --> HOLogic.mk_setT aT) $ f,
  1510          Const ("Finite_Set.Finites", HOLogic.mk_setT (HOLogic.mk_setT aT)))))
  1521          Const ("Finite_Set.Finites", HOLogic.mk_setT (HOLogic.mk_setT aT)))))
  1511            (rec_fns ~~ rec_fn_Ts)) dt_atomTs);
  1522            (rec_fns ~~ rec_fn_Ts)) dt_atomTs;
       
  1523 
       
  1524     val rec_fresh_thms = map (fn ((aT, eqvt_ths), finite_prems) =>
       
  1525       let
       
  1526         val name = Sign.base_name (fst (dest_Type aT));
       
  1527         val fs_name = PureThy.get_thm thy11 (Name ("fs_" ^ name ^ "1"));
       
  1528         val a = Free ("a", aT);
       
  1529         val freshs = map (fn (f, fT) => HOLogic.mk_Trueprop
       
  1530             (Const ("Nominal.fresh", aT --> fT --> HOLogic.boolT) $ a $ f))
       
  1531           (rec_fns ~~ rec_fn_Ts)
       
  1532       in
       
  1533         map (fn (((T, U), R), eqvt_th) =>
       
  1534           let
       
  1535             val x = Free ("x", T);
       
  1536             val y = Free ("y", U);
       
  1537             val y' = Free ("y'", U)
       
  1538           in
       
  1539             standard (Goal.prove (Context.init_proof thy11) [] (finite_prems @
       
  1540                 [HOLogic.mk_Trueprop (HOLogic.mk_mem
       
  1541                   (HOLogic.mk_prod (x, y), R)),
       
  1542                  HOLogic.mk_Trueprop (HOLogic.mk_all ("y'", U,
       
  1543                    HOLogic.mk_imp (HOLogic.mk_mem
       
  1544                        (HOLogic.mk_prod (x, y'), R),
       
  1545                      HOLogic.mk_eq (y', y)))),
       
  1546                  HOLogic.mk_Trueprop (Const ("Nominal.fresh",
       
  1547                    aT --> T --> HOLogic.boolT) $ a $ x)] @
       
  1548               freshs)
       
  1549               (HOLogic.mk_Trueprop (Const ("Nominal.fresh",
       
  1550                  aT --> U --> HOLogic.boolT) $ a $ y))
       
  1551               (fn {prems, context} =>
       
  1552                  let
       
  1553                    val (finite_prems, rec_prem :: unique_prem ::
       
  1554                      fresh_prems) = chop (length finite_prems) prems;
       
  1555                    val unique_prem' = unique_prem RS spec RS mp;
       
  1556                    val unique = [unique_prem', unique_prem' RS sym] MRS trans;
       
  1557                    val _ $ (_ $ (_ $ S $ _)) $ _ = prop_of supports_fresh;
       
  1558                    val tuple = foldr1 HOLogic.mk_prod (x :: rec_fns)
       
  1559                  in EVERY
       
  1560                    [rtac (Drule.cterm_instantiate
       
  1561                       [(cterm_of thy11 S,
       
  1562                         cterm_of thy11 (Const ("Nominal.supp",
       
  1563                           fastype_of tuple --> HOLogic.mk_setT aT) $ tuple))]
       
  1564                       supports_fresh) 1,
       
  1565                     simp_tac (HOL_basic_ss addsimps
       
  1566                       [supports_def, symmetric fresh_def, fresh_prod]) 1,
       
  1567                     REPEAT_DETERM (resolve_tac [allI, impI] 1),
       
  1568                     REPEAT_DETERM (etac conjE 1),
       
  1569                     rtac unique 1,
       
  1570                     SUBPROOF (fn {prems = prems', params = [a, b], ...} => EVERY
       
  1571                       [cut_facts_tac [rec_prem] 1,
       
  1572                        rtac (Thm.instantiate ([],
       
  1573                          [(cterm_of thy11 (Var (("pi", 0), mk_permT aT)),
       
  1574                            cterm_of thy11 (perm_of_pair (term_of a, term_of b)))]) eqvt_th) 1,
       
  1575                        asm_simp_tac (HOL_ss addsimps
       
  1576                          (prems' @ perm_swap @ perm_fresh_fresh)) 1]) context 1,
       
  1577                     rtac rec_prem 1,
       
  1578                     simp_tac (HOL_ss addsimps (fs_name ::
       
  1579                       supp_prod :: finite_Un :: finite_prems)) 1,
       
  1580                     simp_tac (HOL_ss addsimps (symmetric fresh_def ::
       
  1581                       fresh_prod :: fresh_prems)) 1]
       
  1582                  end))
       
  1583           end) (recTs ~~ rec_result_Ts ~~ rec_sets ~~ eqvt_ths)
       
  1584       end) (dt_atomTs ~~ rec_equiv_thms' ~~ finite_premss);
       
  1585 
       
  1586     (** uniqueness **)
       
  1587 
       
  1588     val exists_fresh = PureThy.get_thms thy11 (Name "exists_fresh");
       
  1589     val fs_atoms = map (fn Type (s, _) => PureThy.get_thm thy11
       
  1590       (Name ("fs_" ^ Sign.base_name s ^ "1"))) dt_atomTs;
       
  1591     val fresh_atm = PureThy.get_thms thy11 (Name "fresh_atm");
       
  1592     val calc_atm = PureThy.get_thms thy11 (Name "calc_atm");
       
  1593     val fresh_left = PureThy.get_thms thy11 (Name "fresh_left");
  1512 
  1594 
  1513     val fun_tuple = foldr1 HOLogic.mk_prod rec_fns;
  1595     val fun_tuple = foldr1 HOLogic.mk_prod rec_fns;
  1514     val fun_tupleT = fastype_of fun_tuple;
  1596     val fun_tupleT = fastype_of fun_tuple;
  1515     val rec_unique_frees =
  1597     val rec_unique_frees =
  1516       DatatypeProp.indexify_names (replicate (length recTs) "x") ~~ recTs;
  1598       DatatypeProp.indexify_names (replicate (length recTs) "x") ~~ recTs;
  1518       DatatypeProp.indexify_names (replicate (length recTs) "y") ~~ rec_result_Ts;
  1600       DatatypeProp.indexify_names (replicate (length recTs) "y") ~~ rec_result_Ts;
  1519     val rec_unique_concls = map (fn ((x as (_, T), U), R) =>
  1601     val rec_unique_concls = map (fn ((x as (_, T), U), R) =>
  1520         Const ("Ex1", (U --> HOLogic.boolT) --> HOLogic.boolT) $
  1602         Const ("Ex1", (U --> HOLogic.boolT) --> HOLogic.boolT) $
  1521           Abs ("y", U, HOLogic.mk_mem (HOLogic.pair_const T U $ Free x $ Bound 0, R)))
  1603           Abs ("y", U, HOLogic.mk_mem (HOLogic.pair_const T U $ Free x $ Bound 0, R)))
  1522       (rec_unique_frees ~~ rec_result_Ts ~~ rec_sets);
  1604       (rec_unique_frees ~~ rec_result_Ts ~~ rec_sets);
       
  1605 
  1523     val induct_aux_rec = Drule.cterm_instantiate
  1606     val induct_aux_rec = Drule.cterm_instantiate
  1524       (map (pairself (cterm_of thy11))
  1607       (map (pairself (cterm_of thy11))
  1525          (map (fn (aT, f) => (Logic.varify f, Abs ("z", HOLogic.unitT,
  1608          (map (fn (aT, f) => (Logic.varify f, Abs ("z", HOLogic.unitT,
  1526             Const ("Nominal.supp", fun_tupleT --> HOLogic.mk_setT aT) $ fun_tuple)))
  1609             Const ("Nominal.supp", fun_tupleT --> HOLogic.mk_setT aT) $ fun_tuple)))
  1527               fresh_fs @
  1610               fresh_fs @
  1530             Abs ("z", HOLogic.unitT, absfree (x, U, Q))))
  1613             Abs ("z", HOLogic.unitT, absfree (x, U, Q))))
  1531               (pnames ~~ recTs ~~ rec_unique_frees ~~ rec_unique_concls) @
  1614               (pnames ~~ recTs ~~ rec_unique_frees ~~ rec_unique_concls) @
  1532           map (fn (s, T) => (Var ((s, 0), Logic.varifyT T), Free (s, T)))
  1615           map (fn (s, T) => (Var ((s, 0), Logic.varifyT T), Free (s, T)))
  1533             rec_unique_frees)) induct_aux;
  1616             rec_unique_frees)) induct_aux;
  1534 
  1617 
  1535     val rec_unique = map standard (split_conj_thm (Goal.prove_global thy11 []
  1618     fun obtain_fresh_name vs ths rec_fin_supp T (freshs1, freshs2, ctxt) =
  1536       (fresh_prems @ rec_prems @ rec_prems')
  1619       let
       
  1620         val p = foldr1 HOLogic.mk_prod (vs @ freshs1);
       
  1621         val ex = Goal.prove ctxt [] [] (HOLogic.mk_Trueprop
       
  1622             (HOLogic.exists_const T $ Abs ("x", T,
       
  1623               Const ("Nominal.fresh", T --> fastype_of p --> HOLogic.boolT) $
       
  1624                 Bound 0 $ p)))
       
  1625           (fn _ => EVERY
       
  1626             [cut_facts_tac ths 1,
       
  1627              REPEAT_DETERM (dresolve_tac (the (AList.lookup op = rec_fin_supp T)) 1),
       
  1628              resolve_tac exists_fresh 1,
       
  1629              asm_simp_tac (HOL_ss addsimps (supp_prod :: finite_Un :: fs_atoms)) 1]);
       
  1630         val (([cx], ths), ctxt') = Obtain.result
       
  1631           (fn _ => EVERY
       
  1632             [etac exE 1,
       
  1633              full_simp_tac (HOL_ss addsimps (fresh_prod :: fresh_atm)) 1,
       
  1634              REPEAT (etac conjE 1)])
       
  1635           [ex] ctxt
       
  1636       in (freshs1 @ [term_of cx], freshs2 @ ths, ctxt') end;
       
  1637 
       
  1638     val rec_unique = map standard (split_conj_thm (Goal.prove
       
  1639       (Context.init_proof thy11) []
       
  1640       (List.concat finite_premss @ rec_prems @ rec_prems')
  1537       (HOLogic.mk_Trueprop (foldr1 HOLogic.mk_conj rec_unique_concls))
  1641       (HOLogic.mk_Trueprop (foldr1 HOLogic.mk_conj rec_unique_concls))
  1538       (fn ths =>
  1642       (fn {prems, context} =>
  1539          let
  1643          let
  1540            val k = length rec_fns;
  1644            val k = length rec_fns;
  1541            val (finite_thss, ths1) = funpow (length dt_atomTs) (fn (xss, ys) =>
  1645            val (finite_thss, ths1) = fold_map (fn T => fn xs =>
  1542              apfst (curry op @ xss o single) (chop k ys)) ([], ths);
  1646              apfst (pair T) (chop k xs)) dt_atomTs prems;
  1543            val (P_ind_ths, ths2) = chop k ths1;
  1647            val (P_ind_ths, ths2) = chop k ths1;
  1544            val P_ths = map (fn th => th RS mp) (split_conj_thm
  1648            val P_ths = map (fn th => th RS mp) (split_conj_thm
  1545              (Goal.prove (Context.init_proof thy11)
  1649              (Goal.prove context
  1546                (map fst (rec_unique_frees @ rec_unique_frees')) []
  1650                (map fst (rec_unique_frees @ rec_unique_frees')) []
  1547                (HOLogic.mk_Trueprop (foldr1 HOLogic.mk_conj
  1651                (HOLogic.mk_Trueprop (foldr1 HOLogic.mk_conj
  1548                   (map (fn (((x, y), S), P) => HOLogic.mk_imp (HOLogic.mk_mem
  1652                   (map (fn (((x, y), S), P) => HOLogic.mk_imp (HOLogic.mk_mem
  1549                     (HOLogic.mk_prod (Free x, Free y), S), P $ (Free y)))
  1653                     (HOLogic.mk_prod (Free x, Free y), S), P $ (Free y)))
  1550                       (rec_unique_frees ~~ rec_unique_frees' ~~ rec_sets ~~ rec_preds))))
  1654                       (rec_unique_frees ~~ rec_unique_frees' ~~ rec_sets ~~ rec_preds))))
  1551                (fn _ =>
  1655                (fn _ =>
  1552                   rtac rec_induct 1 THEN
  1656                   rtac rec_induct 1 THEN
  1553                   REPEAT ((resolve_tac P_ind_ths THEN_ALL_NEW assume_tac) 1))))
  1657                   REPEAT ((resolve_tac P_ind_ths THEN_ALL_NEW assume_tac) 1))));
       
  1658            val rec_fin_supp_thms' = map
       
  1659              (fn (ths, (T, fin_ths)) => (T, map (curry op MRS fin_ths) ths))
       
  1660              (rec_fin_supp_thms ~~ finite_thss);
       
  1661            val fcbs = List.concat (map split_conj_thm ths2);
  1554          in EVERY
  1662          in EVERY
  1555            ([rtac induct_aux_rec 1] @
  1663            ([rtac induct_aux_rec 1] @
  1556             List.concat (map (fn finite_ths =>
  1664             List.concat (map (fn (_, finite_ths) =>
  1557               [cut_facts_tac finite_ths 1,
  1665               [cut_facts_tac finite_ths 1,
  1558                asm_simp_tac (HOL_ss addsimps [supp_prod, finite_Un]) 1]) finite_thss) @
  1666                asm_simp_tac (HOL_ss addsimps [supp_prod, finite_Un]) 1]) finite_thss) @
  1559             [ALLGOALS (full_simp_tac (HOL_ss addsimps [symmetric fresh_def, supp_prod, Un_iff])),
  1667             [ALLGOALS (EVERY'
  1560              print_tac "after application of induction theorem",
  1668                [full_simp_tac (HOL_ss addsimps [symmetric fresh_def, supp_prod, Un_iff]),
  1561              setmp quick_and_dirty true (SkipProof.cheat_tac thy11) (** FIXME !! **)])
  1669                 REPEAT_DETERM o eresolve_tac [conjE, ex1E],
       
  1670                 rtac ex1I,
       
  1671                 resolve_tac rec_intrs THEN_ALL_NEW atac,
       
  1672                 rotate_tac ~1,
       
  1673                 (DETERM o eresolve_tac rec_elims) THEN_ALL_NEW full_simp_tac
       
  1674                   (HOL_ss addsimps (Pair_eq :: List.concat distinct_thms)),
       
  1675                 TRY o (etac conjE THEN' hyp_subst_tac)])] @
       
  1676              map (fn idxs => SUBPROOF
       
  1677                (fn {asms, concl, prems = prems', params, context = context', ...} =>
       
  1678                   let
       
  1679                     val (_, prem) = split_last prems';
       
  1680                     val _ $ (_ $ lhs $ rhs) = prop_of prem;
       
  1681                     val _ $ (_ $ lhs' $ rhs') = term_of concl;
       
  1682                     val rT = fastype_of lhs';
       
  1683                     val (c, cargsl) = strip_comb lhs;
       
  1684                     val cargsl' = partition_cargs idxs cargsl;
       
  1685                     val boundsl = List.concat (map fst cargsl');
       
  1686                     val (_, cargsr) = strip_comb rhs;
       
  1687                     val cargsr' = partition_cargs idxs cargsr;
       
  1688                     val boundsr = List.concat (map fst cargsr');
       
  1689                     val (params1, _ :: params2) =
       
  1690                       chop (length params div 2) (map term_of params);
       
  1691                     val params' = params1 @ params2;
       
  1692                     val rec_prems = filter (fn th => case prop_of th of
       
  1693                       _ $ (Const ("op :", _) $ _ $ _) => true | _ => false) prems';
       
  1694                     val fresh_prems = filter (fn th => case prop_of th of
       
  1695                         _ $ (Const ("Nominal.fresh", _) $ _ $ _) => true
       
  1696                       | _ $ (Const ("Not", _) $ _) => true
       
  1697                       | _ => false) prems';
       
  1698                     val Ts = map fastype_of boundsl;
       
  1699 
       
  1700                     val _ = warning "step 1: obtaining fresh names";
       
  1701                     val (freshs1, freshs2, context'') = fold
       
  1702                       (obtain_fresh_name (rec_fns @ params')
       
  1703                          (List.concat (map snd finite_thss) @ rec_prems)
       
  1704                          rec_fin_supp_thms')
       
  1705                       Ts ([], [], context');
       
  1706                     val pi1 = map perm_of_pair (boundsl ~~ freshs1);
       
  1707                     val rpi1 = rev pi1;
       
  1708                     val pi2 = map perm_of_pair (boundsr ~~ freshs1);
       
  1709 
       
  1710                     fun mk_not_sym ths = List.concat (map (fn th =>
       
  1711                       case prop_of th of
       
  1712                           _ $ (Const ("Not", _) $ _) => [th, th RS not_sym]
       
  1713                         | _ => [th]) ths);
       
  1714                     val fresh_prems' = mk_not_sym fresh_prems;
       
  1715                     val freshs2' = mk_not_sym freshs2;
       
  1716 
       
  1717                     (** as, bs, cs # K as ts, K bs us **)
       
  1718                     val _ = warning "step 2: as, bs, cs # K as ts, K bs us";
       
  1719                     val prove_fresh_ss = HOL_ss addsimps
       
  1720                       (finite_Diff :: List.concat fresh_thms @
       
  1721                        fs_atoms @ abs_fresh @ abs_supp @ fresh_atm);
       
  1722                     (* FIXME: avoid asm_full_simp_tac ? *)
       
  1723                     fun prove_fresh ths y x = Goal.prove context'' [] []
       
  1724                       (HOLogic.mk_Trueprop (Const ("Nominal.fresh",
       
  1725                          fastype_of x --> fastype_of y --> HOLogic.boolT) $ x $ y))
       
  1726                       (fn _ => cut_facts_tac ths 1 THEN asm_full_simp_tac prove_fresh_ss 1);
       
  1727                     val constr_fresh_thms =
       
  1728                       map (prove_fresh fresh_prems lhs) boundsl @
       
  1729                       map (prove_fresh fresh_prems rhs) boundsr @
       
  1730                       map (prove_fresh freshs2 lhs) freshs1 @
       
  1731                       map (prove_fresh freshs2 rhs) freshs1;
       
  1732 
       
  1733                     (** pi1 o (K as ts) = pi2 o (K bs us) **)
       
  1734                     val _ = warning "step 3: pi1 o (K as ts) = pi2 o (K bs us)";
       
  1735                     val pi1_pi2_eq = Goal.prove context'' [] []
       
  1736                       (HOLogic.mk_Trueprop (HOLogic.mk_eq
       
  1737                         (foldr (mk_perm []) lhs pi1, foldr (mk_perm []) rhs pi2)))
       
  1738                       (fn _ => EVERY
       
  1739                          [cut_facts_tac constr_fresh_thms 1,
       
  1740                           asm_simp_tac (HOL_basic_ss addsimps perm_fresh_fresh) 1,
       
  1741                           rtac prem 1]);
       
  1742 
       
  1743                     (** pi1 o ts = pi2 o us **)
       
  1744                     val _ = warning "step 4: pi1 o ts = pi2 o us";
       
  1745                     val pi1_pi2_eqs = map (fn (t, u) =>
       
  1746                       Goal.prove context'' [] []
       
  1747                         (HOLogic.mk_Trueprop (HOLogic.mk_eq
       
  1748                           (foldr (mk_perm []) t pi1, foldr (mk_perm []) u pi2)))
       
  1749                         (fn _ => EVERY
       
  1750                            [cut_facts_tac [pi1_pi2_eq] 1,
       
  1751                             asm_full_simp_tac (HOL_ss addsimps
       
  1752                               (calc_atm @ List.concat perm_simps' @
       
  1753                                fresh_prems' @ freshs2' @ abs_perm @
       
  1754                                alpha @ List.concat inject_thms)) 1]))
       
  1755                         (map snd cargsl' ~~ map snd cargsr');
       
  1756 
       
  1757                     (** pi1^-1 o pi2 o us = ts **)
       
  1758                     val _ = warning "step 5: pi1^-1 o pi2 o us = ts";
       
  1759                     val rpi1_pi2_eqs = map (fn ((t, u), eq) =>
       
  1760                       Goal.prove context'' [] []
       
  1761                         (HOLogic.mk_Trueprop (HOLogic.mk_eq
       
  1762                           (foldr (mk_perm []) u (rpi1 @ pi2), t)))
       
  1763                         (fn _ => simp_tac (HOL_ss addsimps
       
  1764                            ((eq RS sym) :: perm_swap)) 1))
       
  1765                         (map snd cargsl' ~~ map snd cargsr' ~~ pi1_pi2_eqs);
       
  1766 
       
  1767                     val (rec_prems1, rec_prems2) =
       
  1768                       chop (length rec_prems div 2) rec_prems;
       
  1769 
       
  1770                     (** (ts, pi1^-1 o pi2 o vs) in rec_set **)
       
  1771                     val _ = warning "step 6: (ts, pi1^-1 o pi2 o vs) in rec_set";
       
  1772                     val rec_prems' = map (fn th =>
       
  1773                       let
       
  1774                         val _ $ (_ $ (_ $ x $ y) $ S) = prop_of th;
       
  1775                         val k = find_index (equal S) rec_sets;
       
  1776                         val pi = rpi1 @ pi2;
       
  1777                         fun mk_pi z = foldr (mk_perm []) z pi;
       
  1778                         fun eqvt_tac p =
       
  1779                           let
       
  1780                             val U as Type (_, [Type (_, [T, _])]) = fastype_of p;
       
  1781                             val l = find_index (equal T) dt_atomTs;
       
  1782                             val th = List.nth (List.nth (rec_equiv_thms', l), k);
       
  1783                             val th' = Thm.instantiate ([],
       
  1784                               [(cterm_of thy11 (Var (("pi", 0), U)),
       
  1785                                 cterm_of thy11 p)]) th;
       
  1786                           in rtac th' 1 end;
       
  1787                         val th' = Goal.prove context'' [] []
       
  1788                           (HOLogic.mk_Trueprop (HOLogic.mk_mem
       
  1789                             (HOLogic.mk_prod (mk_pi x, mk_pi y), S)))
       
  1790                           (fn _ => EVERY
       
  1791                              (map eqvt_tac pi @
       
  1792                               [simp_tac (HOL_ss addsimps (fresh_prems' @ freshs2' @
       
  1793                                  perm_swap @ perm_fresh_fresh)) 1,
       
  1794                                rtac th 1]))
       
  1795                       in
       
  1796                         Simplifier.simplify
       
  1797                           (HOL_basic_ss addsimps rpi1_pi2_eqs) th'
       
  1798                       end) rec_prems2;
       
  1799 
       
  1800                     val ihs = filter (fn th => case prop_of th of
       
  1801                       _ $ (Const ("All", _) $ _) => true | _ => false) prems';
       
  1802 
       
  1803                     (** pi1 o rs = p2 o vs , rs = pi1^-1 o pi2 o vs **)
       
  1804                     val _ = warning "step 7: pi1 o rs = p2 o vs , rs = pi1^-1 o pi2 o vs";
       
  1805                     val (rec_eqns1, rec_eqns2) = ListPair.unzip (map (fn (th, ih) =>
       
  1806                       let
       
  1807                         val th' = th RS (ih RS spec RS mp) RS sym;
       
  1808                         val _ $ (_ $ lhs $ rhs) = prop_of th';
       
  1809                         fun strip_perm (_ $ _ $ t) = strip_perm t
       
  1810                           | strip_perm t = t;
       
  1811                       in
       
  1812                         (Goal.prove context'' [] []
       
  1813                            (HOLogic.mk_Trueprop (HOLogic.mk_eq
       
  1814                               (foldr (mk_perm []) lhs pi1,
       
  1815                                foldr (mk_perm []) (strip_perm rhs) pi2)))
       
  1816                            (fn _ => simp_tac (HOL_basic_ss addsimps
       
  1817                               (th' :: perm_swap)) 1),
       
  1818                          th')
       
  1819                       end) (rec_prems' ~~ ihs));
       
  1820 
       
  1821                     (** as # rs , bs # vs **)
       
  1822                     val _ = warning "step 8: as # rs , bs # vs";
       
  1823                     val (rec_freshs1, rec_freshs2) = ListPair.unzip (List.concat
       
  1824                       (map (fn (((rec_prem, rec_prem'), eqn), ih) =>
       
  1825                         let
       
  1826                           val _ $ (_ $ (_ $ x $ (y as Free (_, T))) $ S) =
       
  1827                             prop_of rec_prem;
       
  1828                           val _ $ (_ $ (_ $ _ $ y') $ _) = prop_of rec_prem';
       
  1829                           val k = find_index (equal S) rec_sets;
       
  1830                           val atoms = List.concat (List.mapPartial
       
  1831                             (fn ((bs, z), (bs', _)) =>
       
  1832                               if z = x then NONE else SOME (bs ~~ bs'))
       
  1833                             (cargsl' ~~ cargsr'))
       
  1834                         in
       
  1835                           map (fn (a as Free (_, aT), b) =>
       
  1836                             let
       
  1837                               val l = find_index (equal aT) dt_atomTs;
       
  1838                               val th = Goal.prove context'' [] []
       
  1839                                 (HOLogic.mk_Trueprop (Const ("Nominal.fresh",
       
  1840                                   aT --> T --> HOLogic.boolT) $ a $ y))
       
  1841                                 (fn _ => EVERY
       
  1842                                    (rtac (List.nth (List.nth (rec_fresh_thms, l), k)) 1 ::
       
  1843                                     map (fn th => rtac th 1)
       
  1844                                       (snd (List.nth (finite_thss, l))) @
       
  1845                                     [rtac rec_prem 1, rtac ih 1,
       
  1846                                      REPEAT_DETERM (resolve_tac fresh_prems 1)]));
       
  1847                               val th' = Goal.prove context'' [] []
       
  1848                                 (HOLogic.mk_Trueprop (Const ("Nominal.fresh",
       
  1849                                   aT --> T --> HOLogic.boolT) $ b $ y'))
       
  1850                                 (fn _ => cut_facts_tac [th] 1 THEN
       
  1851                                     asm_full_simp_tac (HOL_ss addsimps (eqn ::
       
  1852                                       fresh_left @ fresh_prems' @ freshs2' @
       
  1853                                       rev_simps @ app_simps @ calc_atm)) 1)
       
  1854                             in (th, th') end) atoms
       
  1855                         end) (rec_prems1 ~~ rec_prems2 ~~ rec_eqns2 ~~ ihs)));
       
  1856 
       
  1857                     (** as # fK as ts rs , bs # fK bs us vs **)
       
  1858                     val _ = warning "step 9: as # fK as ts rs , bs # fK bs us vs";
       
  1859                     fun prove_fresh_result t (a as Free (_, aT)) =
       
  1860                       Goal.prove context'' [] []
       
  1861                         (HOLogic.mk_Trueprop (Const ("Nominal.fresh",
       
  1862                           aT --> rT --> HOLogic.boolT) $ a $ t))
       
  1863                         (fn _ => EVERY
       
  1864                            [resolve_tac fcbs 1,
       
  1865                             REPEAT_DETERM (resolve_tac
       
  1866                               (fresh_prems @ rec_freshs1 @ rec_freshs2) 1),
       
  1867                             resolve_tac P_ind_ths 1,
       
  1868                             REPEAT_DETERM (resolve_tac (P_ths @ rec_prems) 1)]);
       
  1869         
       
  1870                     val fresh_results =
       
  1871                       map (prove_fresh_result rhs') (List.concat (map fst cargsl')) @
       
  1872                       map (prove_fresh_result lhs') (List.concat (map fst cargsr'));
       
  1873 
       
  1874                     (** cs # fK as ts rs , cs # fK bs us vs **)
       
  1875                     val _ = warning "step 10: cs # fK as ts rs , cs # fK bs us vs";
       
  1876                     fun prove_fresh_result' recs t (a as Free (_, aT)) =
       
  1877                       Goal.prove context'' [] []
       
  1878                         (HOLogic.mk_Trueprop (Const ("Nominal.fresh",
       
  1879                           aT --> rT --> HOLogic.boolT) $ a $ t))
       
  1880                         (fn _ => EVERY
       
  1881                           [cut_facts_tac recs 1,
       
  1882                            REPEAT_DETERM (dresolve_tac
       
  1883                              (the (AList.lookup op = rec_fin_supp_thms' aT)) 1),
       
  1884                            NominalPermeq.fresh_guess_tac
       
  1885                              (HOL_ss addsimps (freshs2 @
       
  1886                                 fs_atoms @ fresh_atm @
       
  1887                                 List.concat (map snd finite_thss))) 1]);
       
  1888 
       
  1889                     val fresh_results' =
       
  1890                       map (prove_fresh_result' rec_prems1 rhs') freshs1 @
       
  1891                       map (prove_fresh_result' rec_prems2 lhs') freshs1;
       
  1892 
       
  1893                     (** pi1 o (fK as ts rs) = pi2 o (fK bs us vs) **)
       
  1894                     val _ = warning "step 11: pi1 o (fK as ts rs) = pi2 o (fK bs us vs)";
       
  1895                     val pi1_pi2_result = Goal.prove context'' [] []
       
  1896                       (HOLogic.mk_Trueprop (HOLogic.mk_eq
       
  1897                         (foldr (mk_perm []) rhs' pi1, foldr (mk_perm []) lhs' pi2)))
       
  1898                       (fn _ => NominalPermeq.perm_simp_tac (HOL_ss addsimps
       
  1899                            pi1_pi2_eqs @ rec_eqns1) 1 THEN
       
  1900                          TRY (simp_tac (HOL_ss addsimps
       
  1901                            (fresh_prems' @ freshs2' @ calc_atm @ perm_fresh_fresh)) 1));
       
  1902 
       
  1903                     val _ = warning "final result";
       
  1904                     val final = Goal.prove context'' [] [] (term_of concl)
       
  1905                       (fn _ => cut_facts_tac [pi1_pi2_result RS sym] 1 THEN
       
  1906                         full_simp_tac (HOL_basic_ss addsimps perm_fresh_fresh @
       
  1907                           fresh_results @ fresh_results') 1);
       
  1908                     val final' = ProofContext.export context'' context' [final];
       
  1909                     val _ = warning "finished!"
       
  1910                   in
       
  1911                     resolve_tac final' 1
       
  1912                   end) context 1) (filter_out null (List.concat (map snd ndescr))))
  1562          end)));
  1913          end)));
  1563     
  1914     
  1564     (* FIXME: theorems are stored in database for testing only *)
  1915     (* FIXME: theorems are stored in database for testing only *)
  1565     val (_, thy12) = thy11 |>
  1916     val (_, thy12) = thy11 |>
  1566       Theory.add_path big_name |>
  1917       Theory.add_path big_name |>
  1567       PureThy.add_thmss
  1918       PureThy.add_thmss
  1568         [(("rec_equiv", List.concat rec_equiv_thms), []),
  1919         [(("rec_equiv", List.concat rec_equiv_thms), []),
  1569          (("rec_equiv'", List.concat rec_equiv_thms'), []),
  1920          (("rec_equiv'", List.concat rec_equiv_thms'), []),
  1570          (("rec_fin_supp", List.concat rec_fin_supp_thms), []),
  1921          (("rec_fin_supp", List.concat rec_fin_supp_thms), []),
       
  1922          (("rec_fresh", List.concat rec_fresh_thms), []),
  1571          (("rec_unique", rec_unique), [])] ||>
  1923          (("rec_unique", rec_unique), [])] ||>
  1572       Theory.parent_path;
  1924       Theory.parent_path;
  1573 
  1925 
  1574   in
  1926   in
  1575     thy12
  1927     thy12