1219820Sjeffstructure tuerk_tacticsLib :> tuerk_tacticsLib =
2219820Sjeffstruct
3219820Sjeff
4219820Sjeff
5219820Sjeff  open HolKernel boolLib bossLib Abbrev metisLib pred_setTheory numLib schneiderUtils
6219820Sjeff
7219820Sjeff   val ERR = mk_HOL_ERR "tuerk_tacticsLib";
8219820Sjeff
9219820Sjeff   val SET_INDUCT_TAC = PSet_ind.SET_INDUCT_TAC FINITE_INDUCT;
10219820Sjeff
11219820Sjeff   val EXISTS_EQ_STRIP_TAC :tactic = fn (asl,t) =>
12219820Sjeff
13219820Sjeff      let val (lhs,rhs) = dest_eq t
14219820Sjeff         val (lvar,LBody) = dest_exists lhs
15219820Sjeff         val (rvar,RBody) = dest_exists rhs
16219820Sjeff         val newVar = variant (free_varsl (t::asl)) lvar
17219820Sjeff         val newLBody = subst[lvar |-> newVar] LBody
18219820Sjeff         val newRBody = subst[rvar |-> newVar] RBody
19219820Sjeff         val result = mk_eq(newLBody, newRBody)
20219820Sjeff      in ([(asl, result)],
21219820Sjeff         fn thList => EXISTS_EQ newVar (hd(thList)))
22219820Sjeff      end
23219820Sjeff      handle HOL_ERR _ => raise ERR "EXISTS_EQ_STRIP_TAC" "";
24219820Sjeff
25219820Sjeff
26219820Sjeff   val FORALL_EQ_STRIP_TAC :tactic = fn (asl,t) =>
27219820Sjeff
28219820Sjeff      let val (lhs,rhs) = dest_eq t
29219820Sjeff         val (lvar,LBody) = dest_forall lhs
30219820Sjeff         val (rvar,RBody) = dest_forall rhs
31219820Sjeff         val newVar = variant (free_varsl (t::asl)) lvar
32219820Sjeff         val newLBody = subst[lvar |-> newVar] LBody
33219820Sjeff         val newRBody = subst[rvar |-> newVar] RBody
34219820Sjeff         val result = mk_eq(newLBody, newRBody)
35219820Sjeff      in ([(asl, result)],
36219820Sjeff         fn thList => FORALL_EQ newVar (hd thList))
37219820Sjeff      end
38219820Sjeff      handle HOL_ERR _ => raise ERR "FORALL_EQ_STRIP_TAC" "";
39219820Sjeff
40219820Sjeff
41219820Sjeff   val REWRITE_ASSUMPTIONS_TAC = fn rwts =>
42219820Sjeff      POP_ASSUM_LIST (MAP_EVERY (fn thm => STRIP_ASSUME_TAC (REWRITE_RULE rwts thm))) THEN
43219820Sjeff      POP_ASSUM_LIST (MAP_EVERY STRIP_ASSUME_TAC);
44219820Sjeff
45219820Sjeff
46219820Sjeff   val CLEAN_ASSUMPTIONS_TAC =
47219820Sjeff      REWRITE_ASSUMPTIONS_TAC[DE_MORGAN_THM, FORALL_AND_THM, EXISTS_OR_THM];
48219820Sjeff
49219820Sjeff
50219820Sjeff   val ONCE_REWRITE_ASSUMPTIONS_TAC = fn rwts =>
51219820Sjeff      POP_ASSUM_LIST (MAP_EVERY (fn thm => STRIP_ASSUME_TAC (ONCE_REWRITE_RULE rwts thm))) THEN
52219820Sjeff      POP_ASSUM_LIST (MAP_EVERY STRIP_ASSUME_TAC);
53219820Sjeff
54219820Sjeff   val REWRITE_ALL_TAC = fn rwts =>
55219820Sjeff      REWRITE_ASSUMPTIONS_TAC rwts THEN
56219820Sjeff      REWRITE_TAC rwts;
57219820Sjeff
58219820Sjeff   val ONCE_REWRITE_ALL_TAC = fn rwts =>
59219820Sjeff      ONCE_REWRITE_ASSUMPTIONS_TAC rwts THEN
60219820Sjeff      ONCE_REWRITE_TAC rwts;
61219820Sjeff
62219820Sjeff   val SIMP_ASSUMPTIONS_TAC = fn simp => fn rwts =>
63219820Sjeff      POP_ASSUM_LIST (MAP_EVERY (fn thm => STRIP_ASSUME_TAC (SIMP_RULE simp rwts thm))) THEN
64219820Sjeff      POP_ASSUM_LIST (MAP_EVERY STRIP_ASSUME_TAC);
65219820Sjeff
66219820Sjeff   val SIMP_ALL_TAC = fn simp => fn rwts =>
67219820Sjeff      SIMP_ASSUMPTIONS_TAC simp rwts THEN
68219820Sjeff      SIMP_TAC simp rwts;
69219820Sjeff
70219820Sjeff
71219820Sjeff
72219820Sjeff   fun findMatch ([], l2, c) = raise ERR "findMatch" "" |
73219820Sjeff      findMatch (l1, [], c) = raise ERR "findMatch" "" |
74219820Sjeff      findMatch (a::l1, b::l2, []) = findMatch (l1, b::l2, b::l2) |
75219820Sjeff      findMatch (a::l1, l2, b::c) = (if (a = b) then a else findMatch (a::l1, l2, c))
76219820Sjeff
77219820Sjeff
78219820Sjeff   val DISJ_EQ_STRIP_TAC :tactic = fn (asl,t) =>
79219820Sjeff      let val (lhs,rhs) = dest_eq t
80219820Sjeff         val l1 = strip_disj lhs
81219820Sjeff         val l2 = strip_disj rhs
82219820Sjeff         val m = findMatch (l1, l2, l2)
83219820Sjeff      in
84219820Sjeff         (DISJ_CASES_TAC (REWRITE_RULE [EQ_CLAUSES] (SPEC m BOOL_CASES_AX)) THEN ASM_REWRITE_TAC[]) (asl, t)
85219820Sjeff      end
86219820Sjeff      handle HOL_ERR _ => raise ERR "OR_EQ_STRIP_TAC" "";
87219820Sjeff
88219820Sjeff
89219820Sjeff   val CONJ_EQ_STRIP_TAC :tactic = fn (asl,t) =>
90219820Sjeff      let val (lhs,rhs) = dest_eq t
91219820Sjeff         val l1 = strip_conj lhs
92219820Sjeff         val l2 = strip_conj rhs
93219820Sjeff         val m = findMatch (l1, l2, l2)
94219820Sjeff      in
95219820Sjeff         (DISJ_CASES_TAC (REWRITE_RULE [EQ_CLAUSES] (SPEC m BOOL_CASES_AX)) THEN ASM_REWRITE_TAC[]) (asl, t)
96219820Sjeff      end
97219820Sjeff      handle HOL_ERR _ => raise ERR "CONJ_EQ_STRIP_TAC" "";
98219820Sjeff
99219820Sjeff   val C_IMP_EQ_STRIP_TAC :tactic = fn (asl,t) =>
100219820Sjeff      let val (lhs,rhs) = dest_eq t
101219820Sjeff          val (la, lc) = dest_imp lhs;
102219820Sjeff          val (ra, rc) = dest_imp rhs;
103219820Sjeff          val l1 = strip_disj lc
104219820Sjeff          val l2 = strip_disj rc
105219820Sjeff          val m = findMatch (l1, l2, l2)
106219820Sjeff      in
107219820Sjeff         (DISJ_CASES_TAC (REWRITE_RULE [EQ_CLAUSES] (SPEC m BOOL_CASES_AX)) THEN ASM_REWRITE_TAC[]) (asl, t)
108219820Sjeff      end
109219820Sjeff      handle HOL_ERR _ => raise ERR "IMP_EQ_STRIP_TAC" "";
110219820Sjeff
111219820Sjeff   val A_IMP_EQ_STRIP_TAC :tactic = fn (asl,t) =>
112219820Sjeff      let val (lhs,rhs) = dest_eq t
113219820Sjeff          val (la, lc) = dest_imp lhs;
114219820Sjeff          val (ra, rc) = dest_imp rhs;
115219820Sjeff          val l1 = strip_conj la
116219820Sjeff          val l2 = strip_conj ra
117219820Sjeff          val m = findMatch (l1, l2, l2)
118219820Sjeff      in
119219820Sjeff         (DISJ_CASES_TAC (REWRITE_RULE [EQ_CLAUSES] (SPEC m BOOL_CASES_AX)) THEN ASM_REWRITE_TAC[]) (asl, t)
120219820Sjeff      end
121219820Sjeff      handle HOL_ERR _ => raise ERR "IMP_EQ_STRIP_TAC" "";
122219820Sjeff
123219820Sjeff
124219820Sjeff   val BOOL_EQ_STRIP_TAC = FIRST [DISJ_EQ_STRIP_TAC, CONJ_EQ_STRIP_TAC,
125219820Sjeff    A_IMP_EQ_STRIP_TAC, C_IMP_EQ_STRIP_TAC, CHANGED_TAC (REWRITE_TAC [DE_MORGAN_THM])];
126219820Sjeff
127219820Sjeff   fun UNDISCH_KEEP_NO_TAC i =
128219820Sjeff    POP_NO_ASSUM i (fn x=> (ASSUME_TAC x THEN UNDISCH_TAC (concl x) THEN ASSUME_TAC x))
129219820Sjeff
130219820Sjeff
131219820Sjeff   val UNDISCH_HD_TAC = schneiderUtils.UNDISCH_HD_TAC
132219820Sjeff   val UNDISCH_ALL_TAC = schneiderUtils.UNDISCH_ALL_TAC
133219820Sjeff   val UNDISCH_NO_TAC = schneiderUtils.UNDISCH_NO_TAC
134219820Sjeff   val POP_NO_ASSUM = schneiderUtils.POP_NO_ASSUM
135219820Sjeff   val LEFT_DISJ_TAC = schneiderUtils.LEFT_DISJ_TAC
136219820Sjeff   val RIGHT_DISJ_TAC = schneiderUtils.RIGHT_DISJ_TAC
137219820Sjeff   val LEFT_CONJ_TAC = schneiderUtils.LEFT_CONJ_TAC
138219820Sjeff   val RIGHT_CONJ_TAC = schneiderUtils.RIGHT_CONJ_TAC
139219820Sjeff
140219820Sjeff   val WEAKEN_HD_TAC = WEAKEN_TAC (fn f => true);
141219820Sjeff   val WEAKEN_NO_TAC = schneiderUtils.POP_NO_TAC
142219820Sjeff   val IMP_TAC = fn t => ASSUME_TAC t THEN UNDISCH_HD_TAC;
143219820Sjeff   fun GSYM_NO_TAC i = POP_NO_ASSUM i (fn x=> ASSUME_TAC (GSYM x));
144219820Sjeff
145219820Sjeff   fun SUBGOAL_TAC q = Q.SUBGOAL_THEN q STRIP_ASSUME_TAC
146219820Sjeff   fun REMAINS_TAC q = Tactical.REVERSE (SUBGOAL_TAC q)
147219820Sjeff   val SPEC_NO_ASSUM = (fn n => fn S => POP_NO_ASSUM n (fn x=> ASSUME_TAC (SPEC S x)));
148219820Sjeff   val SPECL_NO_ASSUM = (fn n => fn S => POP_NO_ASSUM n (fn x=> ASSUME_TAC (SPECL S x)));
149219820Sjeff
150219820Sjeff
151219820Sjeff   fun Q_SPEC_NO_ASSUM n = Q_TAC (SPEC_NO_ASSUM n);
152219820Sjeff
153219820Sjeff   fun Q_SPECL_NO_ASSUM n [] = ALL_TAC
154219820Sjeff     | Q_SPECL_NO_ASSUM n (h::l) = (Q_SPEC_NO_ASSUM n h THEN Q_SPECL_NO_ASSUM 0 l);
155219820Sjeff
156219820Sjeff   val IMP_TO_EQ_TAC = MATCH_MP_TAC (prove (``(a = b) ==> (a ==> b)``, SIMP_TAC std_ss []));
157219820Sjeff
158219820Sjeff   fun store_simp_thm(name,term,tac) = save_thm(name,
159219820Sjeff            SIMP_RULE std_ss [] (prove(term, tac)));
160219820Sjeff
161219820Sjeff
162219820Sjeff  fun EXISTS_LEAST_TAC___GEN t tac =
163219820Sjeff    let
164219820Sjeff      val thm = EXISTS_LEAST_CONV t;
165219820Sjeff      val (lhs, rhs) = dest_eq (concl thm)
166219820Sjeff      fun ASSUME_MP_TAC thm2 = ASSUME_TAC (EQ_MP thm thm2)
167219820Sjeff    in
168219820Sjeff      SUBGOAL_THEN lhs ASSUME_MP_TAC THEN1 tac
169219820Sjeff    end;
170219820Sjeff
171219820Sjeff  fun EXISTS_LEAST_TAC t = EXISTS_LEAST_TAC___GEN t (METIS_TAC[]);
172219820Sjeff  val Q_EXISTS_LEAST_TAC = Q_TAC EXISTS_LEAST_TAC;
173219820Sjeff
174219820Sjeff
175219820Sjeff
176219820Sjeff  fun PROVE_CONDITION_TAC thm (asl, t) =
177219820Sjeff    let
178219820Sjeff      val (p, c) = dest_imp (concl thm);
179219820Sjeff      fun mp_thm thms =
180219820Sjeff        let
181219820Sjeff          val thm_p = el 1 thms;
182219820Sjeff          val thm_t = el 2 thms;
183219820Sjeff          val thm = MP thm thm_p;
184219820Sjeff          val result = DISCH (concl thm) thm_t;
185219820Sjeff          val result = MP result thm
186219820Sjeff        in
187219820Sjeff          result
188219820Sjeff        end
189219820Sjeff    in
190219820Sjeff      ([(asl, p), (c::asl, t)], mp_thm)
191219820Sjeff    end;
192219820Sjeff
193219820Sjeff  fun PROVE_CONDITION_NO_ASSUM i = POP_NO_ASSUM i PROVE_CONDITION_TAC
194219820Sjeff
195219820Sjeff  fun MATCH_LEFT_EQ_MP_TAC thm =
196219820Sjeff    let
197219820Sjeff      val thm = UNDISCH_ALL (SPEC_ALL thm);
198219820Sjeff      val thm = fst (EQ_IMP_RULE thm);
199219820Sjeff      val thm = GEN_ALL (DISCH_ALL thm)
200219820Sjeff      val thm = REWRITE_RULE [AND_IMP_INTRO] thm
201219820Sjeff    in
202219820Sjeff      MATCH_MP_TAC thm
203219820Sjeff    end
204219820Sjeff
205219820Sjeff  fun MATCH_RIGHT_EQ_MP_TAC thm =
206219820Sjeff    let
207219820Sjeff      val thm = UNDISCH_ALL (SPEC_ALL thm);
208219820Sjeff      val thm = snd (EQ_IMP_RULE thm);
209219820Sjeff      val thm = GEN_ALL (DISCH_ALL thm)
210219820Sjeff      val thm = REWRITE_RULE [AND_IMP_INTRO] thm
211219820Sjeff    in
212219820Sjeff      MATCH_MP_TAC thm
213219820Sjeff    end
214219820Sjeff
215219820Sjeffend
216219820Sjeff