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, |
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) => |