src/HOL/Tools/Transfer/transfer.ML
changeset 70316 c61b7af108a6
parent 70159 57503fe1b0ff
child 70473 9179e7a98196
equal deleted inserted replaced
70315:2f9623aa1eeb 70316:c61b7af108a6
   122       relator_eq_raw = Item_Net.merge (rw1, rw2),
   122       relator_eq_raw = Item_Net.merge (rw1, rw2),
   123       relator_domain = Item_Net.merge (rd1, rd2),
   123       relator_domain = Item_Net.merge (rd1, rd2),
   124       pred_data = Symtab.merge (K true) (pd1, pd2) }
   124       pred_data = Symtab.merge (K true) (pd1, pd2) }
   125 )
   125 )
   126 
   126 
   127 fun get_transfer_raw ctxt = ctxt
   127 val get_transfer_raw = Item_Net.content o #transfer_raw o Data.get o Context.Proof
   128   |> (Item_Net.content o #transfer_raw o Data.get o Context.Proof)
   128 
   129 
   129 val get_known_frees = #known_frees o Data.get o Context.Proof
   130 fun get_known_frees ctxt = ctxt
   130 
   131   |> (#known_frees o Data.get o Context.Proof)
   131 val get_compound_lhs = #compound_lhs o Data.get o Context.Proof
   132 
   132 
   133 fun get_compound_lhs ctxt = ctxt
   133 val get_compound_rhs = #compound_rhs o Data.get o Context.Proof
   134   |> (#compound_lhs o Data.get o Context.Proof)
   134 
   135 
   135 val get_relator_eq_item_net = #relator_eq o Data.get o Context.Proof
   136 fun get_compound_rhs ctxt = ctxt
   136 
   137   |> (#compound_rhs o Data.get o Context.Proof)
   137 val get_relator_eq =
   138 
   138   map safe_mk_meta_eq o Item_Net.content o #relator_eq o Data.get o Context.Proof
   139 fun get_relator_eq_item_net ctxt = (#relator_eq o Data.get o Context.Proof) ctxt
   139 
   140 
   140 val get_sym_relator_eq =
   141 fun get_relator_eq ctxt = ctxt
   141   map (Thm.symmetric o safe_mk_meta_eq) o Item_Net.content o #relator_eq o Data.get o Context.Proof
   142   |> (Item_Net.content o #relator_eq o Data.get o Context.Proof)
   142 
   143   |> map safe_mk_meta_eq
   143 val get_relator_eq_raw = Item_Net.content o #relator_eq_raw o Data.get o Context.Proof
   144 
   144 
   145 fun get_sym_relator_eq ctxt = ctxt
   145 val get_relator_domain = Item_Net.content o #relator_domain o Data.get o Context.Proof
   146   |> (Item_Net.content o #relator_eq o Data.get o Context.Proof)
   146 
   147   |> map (Thm.symmetric o safe_mk_meta_eq)
   147 val get_pred_data = #pred_data o Data.get o Context.Proof
   148 
       
   149 fun get_relator_eq_raw ctxt = ctxt
       
   150   |> (Item_Net.content o #relator_eq_raw o Data.get o Context.Proof)
       
   151 
       
   152 fun get_relator_domain ctxt = ctxt
       
   153   |> (Item_Net.content o #relator_domain o Data.get o Context.Proof)
       
   154 
       
   155 fun get_pred_data ctxt = ctxt
       
   156   |> (#pred_data o Data.get o Context.Proof)
       
   157 
   148 
   158 fun map_data f1 f2 f3 f4 f5 f6 f7 f8
   149 fun map_data f1 f2 f3 f4 f5 f6 f7 f8
   159   { transfer_raw, known_frees, compound_lhs, compound_rhs,
   150   { transfer_raw, known_frees, compound_lhs, compound_rhs,
   160     relator_eq, relator_eq_raw, relator_domain, pred_data } =
   151     relator_eq, relator_eq_raw, relator_domain, pred_data } =
   161   { transfer_raw = f1 transfer_raw,
   152   { transfer_raw = f1 transfer_raw,
   356     val equal_thm = Raw_Simplifier.rewrite ctxt false [Domainp_lemma] cprop
   347     val equal_thm = Raw_Simplifier.rewrite ctxt false [Domainp_lemma] cprop
   357     fun forall_elim thm = Thm.forall_elim_vars (Thm.maxidx_of thm + 1) thm;
   348     fun forall_elim thm = Thm.forall_elim_vars (Thm.maxidx_of thm + 1) thm;
   358   in
   349   in
   359     forall_elim (thm COMP (equal_thm COMP @{thm equal_elim_rule2}))
   350     forall_elim (thm COMP (equal_thm COMP @{thm equal_elim_rule2}))
   360   end
   351   end
   361     handle TERM _ => thm
   352   handle TERM _ => thm
   362 
   353 
   363 fun abstract_domains_transfer ctxt thm =
   354 fun abstract_domains_transfer ctxt thm =
   364   let
   355   let
   365     fun dest prop =
   356     fun dest prop =
   366       let
   357       let
   402     Conv.fconv_rule (Conv.prems_conv ~1 safe_transfer_rule_conv) thm
   393     Conv.fconv_rule (Conv.prems_conv ~1 safe_transfer_rule_conv) thm
   403   end
   394   end
   404 
   395 
   405 (** Adding transfer domain rules **)
   396 (** Adding transfer domain rules **)
   406 
   397 
   407 fun prep_transfer_domain_thm ctxt thm =
   398 fun prep_transfer_domain_thm ctxt =
   408   (abstract_equalities_domain ctxt o detect_transfer_rules) thm
   399   abstract_equalities_domain ctxt o detect_transfer_rules
   409 
   400 
   410 fun add_transfer_domain_thm thm ctxt = (add_transfer_thm o
   401 fun add_transfer_domain_thm thm ctxt =
   411   prep_transfer_domain_thm (Context.proof_of ctxt)) thm ctxt
   402   (add_transfer_thm o prep_transfer_domain_thm (Context.proof_of ctxt)) thm ctxt
   412 
   403 
   413 fun del_transfer_domain_thm thm ctxt = (del_transfer_thm o
   404 fun del_transfer_domain_thm thm ctxt =
   414   prep_transfer_domain_thm (Context.proof_of ctxt)) thm ctxt
   405   (del_transfer_thm o prep_transfer_domain_thm (Context.proof_of ctxt)) thm ctxt
   415 
   406 
   416 (** Transfer proof method **)
   407 (** Transfer proof method **)
   417 
   408 
   418 val post_simps =
   409 val post_simps =
   419   @{thms transfer_forall_eq [symmetric]
   410   @{thms transfer_forall_eq [symmetric]
   493   in
   484   in
   494     Drule.implies_intr_list hyps (thm RS rename)
   485     Drule.implies_intr_list hyps (thm RS rename)
   495   end
   486   end
   496 
   487 
   497 (* create a lambda term of the same shape as the given term *)
   488 (* create a lambda term of the same shape as the given term *)
   498 fun skeleton (is_atom : term -> bool) ctxt t =
   489 fun skeleton is_atom =
   499   let
   490   let
   500     fun dummy ctxt =
   491     fun dummy ctxt =
   501       let
   492       let val (c, ctxt') = yield_singleton Variable.variant_fixes "a" ctxt
   502         val (c, ctxt) = yield_singleton Variable.variant_fixes "a" ctxt
   493       in (Free (c, dummyT), ctxt') end
   503       in
   494     fun skel (Bound i) ctxt = (Bound i, ctxt)
   504         (Free (c, dummyT), ctxt)
   495       | skel (Abs (x, _, t)) ctxt =
   505       end
   496           let val (t', ctxt) = skel t ctxt
   506     fun go (Bound i) ctxt = (Bound i, ctxt)
   497           in (Abs (x, dummyT, t'), ctxt) end
   507       | go (Abs (x, _, t)) ctxt =
   498       | skel (tu as t $ u) ctxt =
   508         let
   499           if is_atom tu andalso not (Term.is_open tu) then dummy ctxt
   509           val (t', ctxt) = go t ctxt
   500           else
   510         in
   501             let
   511           (Abs (x, dummyT, t'), ctxt)
   502               val (t', ctxt) = skel t ctxt
   512         end
   503               val (u', ctxt) = skel u ctxt
   513       | go (tu as (t $ u)) ctxt =
   504             in (t' $ u', ctxt) end
   514         if is_atom tu andalso not (Term.is_open tu) then dummy ctxt else
   505       | skel _ ctxt = dummy ctxt
   515         let
   506   in
   516           val (t', ctxt) = go t ctxt
   507     fn ctxt => fn t =>
   517           val (u', ctxt) = go u ctxt
   508       fst (skel t ctxt) |> Syntax.check_term ctxt  (* FIXME avoid syntax operation!? *)
   518         in
       
   519           (t' $ u', ctxt)
       
   520         end
       
   521       | go _ ctxt = dummy ctxt
       
   522   in
       
   523     go t ctxt |> fst |> Syntax.check_term ctxt
       
   524   end
   509   end
   525 
   510 
   526 (** Monotonicity analysis **)
   511 (** Monotonicity analysis **)
   527 
   512 
   528 (* TODO: Put extensible table in theory data *)
   513 (* TODO: Put extensible table in theory data *)
   578 fun retrieve_terms t net = map fst (Item_Net.retrieve net t)
   563 fun retrieve_terms t net = map fst (Item_Net.retrieve net t)
   579 
   564 
   580 fun matches_list ctxt term =
   565 fun matches_list ctxt term =
   581   is_some o find_first (fn pat => Pattern.matches (Proof_Context.theory_of ctxt) (pat, term))
   566   is_some o find_first (fn pat => Pattern.matches (Proof_Context.theory_of ctxt) (pat, term))
   582 
   567 
   583 fun transfer_rule_of_term ctxt equiv t : thm =
   568 fun transfer_rule_of_term ctxt equiv t =
   584   let
   569   let
   585     val compound_rhs = get_compound_rhs ctxt
   570     val compound_rhs = get_compound_rhs ctxt
   586     fun is_rhs t = compound_rhs |> retrieve_terms t |> matches_list ctxt t
   571     fun is_rhs t = compound_rhs |> retrieve_terms t |> matches_list ctxt t
   587     val s = skeleton is_rhs ctxt t
   572     val s = skeleton is_rhs ctxt t
   588     val frees = map fst (Term.add_frees s [])
   573     val frees = map fst (Term.add_frees s [])
   597     fun tinst (a, _) = (((a, idx), \<^sort>\<open>type\<close>), \<^ctyp>\<open>bool\<close>)
   582     fun tinst (a, _) = (((a, idx), \<^sort>\<open>type\<close>), \<^ctyp>\<open>bool\<close>)
   598     fun inst (a, t) =
   583     fun inst (a, t) =
   599       ((Name.clean_index (prep a, idx), \<^typ>\<open>bool \<Rightarrow> bool \<Rightarrow> bool\<close>), Thm.cterm_of ctxt' t)
   584       ((Name.clean_index (prep a, idx), \<^typ>\<open>bool \<Rightarrow> bool \<Rightarrow> bool\<close>), Thm.cterm_of ctxt' t)
   600   in
   585   in
   601     thm
   586     thm
   602       |> Thm.generalize (tfrees, rnames @ frees) idx
   587     |> Thm.generalize (tfrees, rnames @ frees) idx
   603       |> Thm.instantiate (map tinst binsts, map inst binsts)
   588     |> Thm.instantiate (map tinst binsts, map inst binsts)
   604   end
   589   end
   605 
   590 
   606 fun transfer_rule_of_lhs ctxt t : thm =
   591 fun transfer_rule_of_lhs ctxt t =
   607   let
   592   let
   608     val compound_lhs = get_compound_lhs ctxt
   593     val compound_lhs = get_compound_lhs ctxt
   609     fun is_lhs t = compound_lhs |> retrieve_terms t |> matches_list ctxt t
   594     fun is_lhs t = compound_lhs |> retrieve_terms t |> matches_list ctxt t
   610     val s = skeleton is_lhs ctxt t
   595     val s = skeleton is_lhs ctxt t
   611     val frees = map fst (Term.add_frees s [])
   596     val frees = map fst (Term.add_frees s [])
   620     fun tinst (a, _) = (((a, idx), \<^sort>\<open>type\<close>), \<^ctyp>\<open>bool\<close>)
   605     fun tinst (a, _) = (((a, idx), \<^sort>\<open>type\<close>), \<^ctyp>\<open>bool\<close>)
   621     fun inst (a, t) =
   606     fun inst (a, t) =
   622       ((Name.clean_index (prep a, idx), \<^typ>\<open>bool \<Rightarrow> bool \<Rightarrow> bool\<close>), Thm.cterm_of ctxt' t)
   607       ((Name.clean_index (prep a, idx), \<^typ>\<open>bool \<Rightarrow> bool \<Rightarrow> bool\<close>), Thm.cterm_of ctxt' t)
   623   in
   608   in
   624     thm
   609     thm
   625       |> Thm.generalize (tfrees, rnames @ frees) idx
   610     |> Thm.generalize (tfrees, rnames @ frees) idx
   626       |> Thm.instantiate (map tinst binsts, map inst binsts)
   611     |> Thm.instantiate (map tinst binsts, map inst binsts)
   627   end
   612   end
   628 
   613 
   629 fun eq_rules_tac ctxt eq_rules =
   614 fun eq_rules_tac ctxt eq_rules =
   630   TRY o REPEAT_ALL_NEW (resolve_tac ctxt eq_rules)
   615   TRY o REPEAT_ALL_NEW (resolve_tac ctxt eq_rules)
   631   THEN_ALL_NEW resolve_tac ctxt @{thms is_equality_eq}
   616   THEN_ALL_NEW resolve_tac ctxt @{thms is_equality_eq}
   717 
   702 
   718 (** Transfer attribute **)
   703 (** Transfer attribute **)
   719 
   704 
   720 fun transferred ctxt extra_rules thm =
   705 fun transferred ctxt extra_rules thm =
   721   let
   706   let
   722     val start_rule = @{thm transfer_start}
       
   723     val start_rule' = @{thm transfer_start'}
       
   724     val rules = extra_rules @ get_transfer_raw ctxt
   707     val rules = extra_rules @ get_transfer_raw ctxt
   725     val eq_rules = get_relator_eq_raw ctxt
   708     val eq_rules = get_relator_eq_raw ctxt
   726     val err_msg = "Transfer failed to convert goal to an object-logic formula"
       
   727     val pre_simps = @{thms transfer_forall_eq transfer_implies_eq}
   709     val pre_simps = @{thms transfer_forall_eq transfer_implies_eq}
   728     val thm1 = Drule.forall_intr_vars thm
   710     val thm1 = Drule.forall_intr_vars thm
   729     val instT =
   711     val instT =
   730       rev (Term.add_tvars (Thm.full_prop_of thm1) [])
   712       rev (Term.add_tvars (Thm.full_prop_of thm1) [])
   731       |> map (fn v as ((a, _), S) => (v, Thm.ctyp_of ctxt (TFree (a, S))))
   713       |> map (fn v as ((a, _), S) => (v, Thm.ctyp_of ctxt (TFree (a, S))))
   732     val thm2 = thm1
   714     val thm2 = thm1
   733       |> Thm.instantiate (instT, [])
   715       |> Thm.instantiate (instT, [])
   734       |> Raw_Simplifier.rewrite_rule ctxt pre_simps
   716       |> Raw_Simplifier.rewrite_rule ctxt pre_simps
   735     val ctxt' = Variable.declare_names (Thm.full_prop_of thm2) ctxt
   717     val ctxt' = Variable.declare_names (Thm.full_prop_of thm2) ctxt
   736     val t = HOLogic.dest_Trueprop (Thm.concl_of thm2)
   718     val rule = transfer_rule_of_lhs ctxt' (HOLogic.dest_Trueprop (Thm.concl_of thm2))
   737     val rule = transfer_rule_of_lhs ctxt' t
   719   in
   738     val tac =
   720     Goal.prove_internal ctxt' []
   739       resolve_tac ctxt' [thm2 RS start_rule', thm2 RS start_rule] 1 THEN
   721       (Thm.cterm_of ctxt' (HOLogic.mk_Trueprop (Var (("P", 0), \<^typ>\<open>bool\<close>))))
   740       (resolve_tac ctxt' [rule]
   722       (fn _ =>
   741         THEN_ALL_NEW
   723         resolve_tac ctxt' [thm2 RS @{thm transfer_start'}, thm2 RS @{thm transfer_start}] 1 THEN
   742           (SOLVED' (REPEAT_ALL_NEW (resolve_tac ctxt' rules)
   724         (resolve_tac ctxt' [rule]
   743             THEN_ALL_NEW (DETERM o eq_rules_tac ctxt' eq_rules)))) 1
   725           THEN_ALL_NEW
   744         handle TERM (_, ts) => raise TERM (err_msg, ts)
   726             (SOLVED' (REPEAT_ALL_NEW (resolve_tac ctxt' rules)
   745     val goal = Thm.cterm_of ctxt' (HOLogic.mk_Trueprop (Var (("P", 0), \<^typ>\<open>bool\<close>)))
   727               THEN_ALL_NEW (DETERM o eq_rules_tac ctxt' eq_rules)))) 1
   746     val thm3 = Goal.prove_internal ctxt' [] goal (K tac)
   728           handle TERM (_, ts) =>
   747     val tnames = map (fst o dest_TFree o Thm.typ_of o snd) instT
   729             raise TERM ("Transfer failed to convert goal to an object-logic formula", ts))
   748   in
   730     |> Raw_Simplifier.rewrite_rule ctxt' post_simps
   749     thm3
   731     |> Simplifier.norm_hhf ctxt'
   750       |> Raw_Simplifier.rewrite_rule ctxt' post_simps
   732     |> Drule.generalize (map (fst o dest_TFree o Thm.typ_of o snd) instT, [])
   751       |> Simplifier.norm_hhf ctxt'
   733     |> Drule.zero_var_indexes
   752       |> Drule.generalize (tnames, [])
       
   753       |> Drule.zero_var_indexes
       
   754   end
   734   end
   755 (*
   735 (*
   756     handle THM _ => thm
   736     handle THM _ => thm
   757 *)
   737 *)
   758 
   738 
   759 fun untransferred ctxt extra_rules thm =
   739 fun untransferred ctxt extra_rules thm =
   760   let
   740   let
   761     val start_rule = @{thm untransfer_start}
       
   762     val rules = extra_rules @ get_transfer_raw ctxt
   741     val rules = extra_rules @ get_transfer_raw ctxt
   763     val eq_rules = get_relator_eq_raw ctxt
   742     val eq_rules = get_relator_eq_raw ctxt
   764     val err_msg = "Transfer failed to convert goal to an object-logic formula"
       
   765     val pre_simps = @{thms transfer_forall_eq transfer_implies_eq}
   743     val pre_simps = @{thms transfer_forall_eq transfer_implies_eq}
   766     val thm1 = Drule.forall_intr_vars thm
   744     val thm1 = Drule.forall_intr_vars thm
   767     val instT =
   745     val instT =
   768       rev (Term.add_tvars (Thm.full_prop_of thm1) [])
   746       rev (Term.add_tvars (Thm.full_prop_of thm1) [])
   769       |> map (fn v as ((a, _), S) => (v, Thm.ctyp_of ctxt (TFree (a, S))))
   747       |> map (fn v as ((a, _), S) => (v, Thm.ctyp_of ctxt (TFree (a, S))))
   771       |> Thm.instantiate (instT, [])
   749       |> Thm.instantiate (instT, [])
   772       |> Raw_Simplifier.rewrite_rule ctxt pre_simps
   750       |> Raw_Simplifier.rewrite_rule ctxt pre_simps
   773     val ctxt' = Variable.declare_names (Thm.full_prop_of thm2) ctxt
   751     val ctxt' = Variable.declare_names (Thm.full_prop_of thm2) ctxt
   774     val t = HOLogic.dest_Trueprop (Thm.concl_of thm2)
   752     val t = HOLogic.dest_Trueprop (Thm.concl_of thm2)
   775     val rule = transfer_rule_of_term ctxt' true t
   753     val rule = transfer_rule_of_term ctxt' true t
   776     val tac =
   754   in
   777       resolve_tac ctxt' [thm2 RS start_rule] 1 THEN
   755     Goal.prove_internal ctxt' []
   778       (resolve_tac ctxt' [rule]
   756       (Thm.cterm_of ctxt' (HOLogic.mk_Trueprop (Var (("P", 0), \<^typ>\<open>bool\<close>))))
   779         THEN_ALL_NEW
   757       (fn _ =>
   780           (SOLVED' (REPEAT_ALL_NEW (resolve_tac ctxt' rules)
   758         resolve_tac ctxt' [thm2 RS @{thm untransfer_start}] 1 THEN
   781             THEN_ALL_NEW (DETERM o eq_rules_tac ctxt' eq_rules)))) 1
   759         (resolve_tac ctxt' [rule]
   782         handle TERM (_, ts) => raise TERM (err_msg, ts)
   760           THEN_ALL_NEW
   783     val goal = Thm.cterm_of ctxt' (HOLogic.mk_Trueprop (Var (("P", 0), \<^typ>\<open>bool\<close>)))
   761             (SOLVED' (REPEAT_ALL_NEW (resolve_tac ctxt' rules)
   784     val thm3 = Goal.prove_internal ctxt' [] goal (K tac)
   762               THEN_ALL_NEW (DETERM o eq_rules_tac ctxt' eq_rules)))) 1
   785     val tnames = map (fst o dest_TFree o Thm.typ_of o snd) instT
   763           handle TERM (_, ts) =>
   786   in
   764             raise TERM ("Transfer failed to convert goal to an object-logic formula", ts))
   787     thm3
   765     |> Raw_Simplifier.rewrite_rule ctxt' post_simps
   788       |> Raw_Simplifier.rewrite_rule ctxt' post_simps
   766     |> Simplifier.norm_hhf ctxt'
   789       |> Simplifier.norm_hhf ctxt'
   767     |> Drule.generalize (map (fst o dest_TFree o Thm.typ_of o snd) instT, [])
   790       |> Drule.generalize (tnames, [])
   768     |> Drule.zero_var_indexes
   791       |> Drule.zero_var_indexes
       
   792   end
   769   end
   793 
   770 
   794 (** Methods and attributes **)
   771 (** Methods and attributes **)
   795 
   772 
   796 val free = Args.context -- Args.term >> (fn (_, Free v) => v | (ctxt, t) =>
   773 val free = Args.context -- Args.term >> (fn (_, Free v) => v | (ctxt, t) =>
   861     val morph_thm = Morphism.thm phi
   838     val morph_thm = Morphism.thm phi
   862   in
   839   in
   863     map_pred_data' morph_thm morph_thm (map morph_thm)
   840     map_pred_data' morph_thm morph_thm (map morph_thm)
   864   end
   841   end
   865 
   842 
   866 fun lookup_pred_data ctxt type_name = Symtab.lookup (get_pred_data ctxt) type_name
   843 fun lookup_pred_data ctxt type_name =
       
   844   Symtab.lookup (get_pred_data ctxt) type_name
   867   |> Option.map (morph_pred_data (Morphism.transfer_morphism' ctxt))
   845   |> Option.map (morph_pred_data (Morphism.transfer_morphism' ctxt))
   868 
   846 
   869 fun update_pred_data type_name qinfo ctxt =
   847 fun update_pred_data type_name qinfo ctxt =
   870   Data.map (map_pred_data (Symtab.update (type_name, qinfo))) ctxt
   848   Data.map (map_pred_data (Symtab.update (type_name, qinfo))) ctxt
   871 
   849