1structure congLib :> congLib =
2struct
3
4(*
5quietdec := true;
6
7map load
8 ["liteLib",
9  "computeLib", "simpLib", "Trace", "Traverse", "Opening",
10  "Travrules", "relationTheory", "Cond_rewr"];
11*)
12
13open HolKernel boolLib
14     liteLib computeLib simpLib Trace Traverse Opening
15     Travrules Cond_rewr;
16
17
18(*
19show_assums := false;
20show_assums := true;
21show_types := true;
22show_types := false;
23quietdec := false;
24*)
25
26fun extract_preorder_trans (Travrules.PREORDER(_,TRANS,_)) = TRANS;
27fun extract_preorder_refl (Travrules.PREORDER(_,_,REFL)) = REFL;
28fun extract_preorder_const (Travrules.PREORDER(t,_,_)) = t
29
30(*---------------------------------------------------------------------------*)
31(* Composable congruence set fragments                                       *)
32(*---------------------------------------------------------------------------*)
33
34val AP_TERM_THM = prove (``!f x. (f x x) ==>
35(!y. (x = y) ==> (f x y))``,
36  REPEAT STRIP_TAC THEN
37  POP_ASSUM (fn x=> ASSUME_TAC (GSYM x)) THEN
38  ASM_REWRITE_TAC[]
39);
40
41
42fun mk_preorder_refl preorders preorderTerm =
43  let
44    val preorder = find_relation preorderTerm preorders;
45  in
46    extract_preorder_refl preorder
47  end;
48
49
50fun mk_congprocs preorders congs =
51  let
52    val congs = flatten (map BODY_CONJUNCTS congs)
53    fun gen_refl(x as {Rinst,arg}) = mk_preorder_refl preorders Rinst x
54  in
55    map (CONGPROC gen_refl) congs
56  end
57
58fun mk_refl_rewrite preorder =
59  let
60    val preorderTerm = extract_preorder_const preorder
61    val hol_type = hd (#2 (dest_type (type_of preorderTerm)))
62    val var = mk_var ("x", hol_type)
63    val refl = extract_preorder_refl preorder;
64    val reflThm = refl {Rinst=preorderTerm,arg=var}
65  in
66    EQT_INTRO reflThm
67  end;
68
69
70
71fun mk_eq_congproc preorder =
72  let
73    val preorderTerm = extract_preorder_const preorder
74    val hol_type = hd (#2 (dest_type (type_of preorderTerm)))
75    val var = mk_var ("x", hol_type)
76    val refl = extract_preorder_refl preorder;
77    val reflThm = refl {Rinst=preorderTerm,arg=var}
78    val thm = MATCH_MP AP_TERM_THM reflThm
79    val thm = SPEC_ALL thm
80  in
81    (*The only congruence occuring in an antecedent is =. Thus t == ``$=`` holds for all
82      calls and we can use REFL *)
83    (CONGPROC (fn {Rinst,arg} => REFL arg)) thm
84  end;
85
86
87
88val equalityPreorder = Travrules.EQ_preorder
89
90
91fun is_match_binop binop term =
92  let
93    val operator = rator (rator (term));
94  in
95    same_const operator binop
96  end handle _ => false;
97
98
99local
100  fun cong_rewrite_internal (rel, refl) term boundvars thm =
101      if is_eq (concl thm) then let
102          val congThm = refl term
103          val congThm = CONV_RULE (RAND_CONV (REWR_CONV thm)) congThm
104        in
105          congThm
106        end
107      else let
108          val thm_relation = rator(rator(concl thm))
109          val _ = samerel thm_relation rel orelse
110                  failwith ("not applicable")
111          val thmLHS = rand (rator (concl thm))
112          val match = match_terml [] boundvars thmLHS term
113          val thm = INST_TY_TERM match thm
114        in
115          thm
116        end
117in
118  fun cong_rewrite net preorder term =
119    (let
120      val matches = Ho_Net.lookup term net;
121      val result = tryfind (fn (boundvars, thm) => cong_rewrite_internal preorder term boundvars thm) matches
122    in
123      result
124    end) handle _ => NO_CONV term;
125end
126
127
128
129
130exception CONVNET of (term set * thm) Ho_Net.net;
131
132val cong_reducer =
133  let
134      fun insertThms net thms =
135        let
136          val flatThms = flatten (map BODY_CONJUNCTS thms);
137          fun insert_one (thm, net) =
138            (let
139              val concl = rand (rator (concl thm));
140              val boundvars = free_varsl (hyp thm);
141              val boundvars_set = FVL (hyp thm) empty_varset;
142            in
143              Ho_Net.enter (boundvars, concl, (boundvars_set, thm)) net
144            end) handle _ => net
145        in
146          (foldr insert_one net flatThms)
147        end
148
149      fun addcontext (context,thms) =
150        let
151          val net = (raise context) handle CONVNET net => net
152        in
153          CONVNET (insertThms net thms)
154        end
155      fun apply {solver,conv,context,stack,relation} tm =
156        let
157            val net = ((raise context) handle CONVNET net => net)
158            val thm = cong_rewrite net relation tm
159        in
160          thm
161        end
162  in REDUCER {name=SOME"cong_reducer",
163              addcontext=addcontext, apply=apply,
164              initial=CONVNET (Ho_Net.empty)}
165  end;
166
167
168fun reducer_addRwts (REDUCER {name,addcontext,apply,initial}) rwts =
169  REDUCER {name=name,addcontext=addcontext, apply=apply, initial=addcontext (initial,rwts)}
170
171
172fun eq_reducer_wrapper (eq_reducer as REDUCER data)= let
173  val name = #name data
174  val initial = #initial data
175  val addcontext = #addcontext data
176
177  fun apply {solver,conv,context,stack,relation as (_, refl)} tm = let
178    val eqthm = #apply data
179                       {solver=solver,conv=conv,
180                        context=context,stack=stack,
181                        relation=relation}
182                       tm
183    val congThm = refl tm
184    val congThm = CONV_RULE (RAND_CONV (REWR_CONV eqthm)) congThm
185  in
186    congThm
187  end
188in
189  REDUCER {name=name,addcontext=addcontext, apply=apply, initial=initial}
190end;
191
192
193datatype congsetfrag = CSFRAG of
194   {rewrs  : thm list,
195    relations : preorder list,
196    dprocs : Traverse.reducer list,
197    congs  : thm list};
198
199
200
201datatype congset = CS of
202   {cong_reducer : Traverse.reducer,
203    limit : int option,
204    relations : preorder list,
205    dprocs : Traverse.reducer list,
206    travrules  : travrules list}
207
208val empty_congset = CS {cong_reducer=cong_reducer,
209                    relations=[equalityPreorder],
210                    dprocs=[], limit = NONE,
211                    travrules=[]};
212
213
214 fun add_to_congset
215    (CSFRAG {rewrs, relations=relationsFrag, dprocs=dprocsFrag, congs},
216     CS {cong_reducer, relations, dprocs, travrules, limit})
217  = let
218      val cong_reducer = reducer_addRwts cong_reducer rewrs;
219
220      val refl_rewrites = map mk_refl_rewrite relationsFrag;
221      val cong_reducer = reducer_addRwts cong_reducer refl_rewrites;
222
223      val newRelations = relations@relationsFrag;
224      val newCongs = mk_congprocs newRelations congs;
225      val congsTravrule = TRAVRULES
226        {relations=newRelations,
227        congprocs=newCongs,
228        weakenprocs=[]};
229    in
230      CS {cong_reducer=cong_reducer,
231          relations=relations@relationsFrag,
232          dprocs=dprocs@dprocsFrag,
233          travrules=travrules@[congsTravrule],
234          limit = limit}
235    end;
236
237 val mk_congset = foldl add_to_congset empty_congset;
238 fun cs_addfrag cs csdata = add_to_congset (csdata,cs);
239
240fun dest_congsetfrag (CSFRAG (data)) = data;
241
242fun merge_cs (s:congsetfrag list) =
243    CSFRAG {rewrs=flatten (map (#rewrs o dest_congsetfrag) s),
244            relations=flatten (map (#relations o dest_congsetfrag) s),
245            dprocs=flatten (map (#dprocs o dest_congsetfrag) s),
246            congs=flatten (map (#congs o dest_congsetfrag) s)};
247
248fun csfrag_rewrites rewrs =
249   CSFRAG
250   {rewrs=rewrs,
251    relations = [],
252    dprocs = [],
253    congs  = []};
254
255
256fun add_csfrag_rewrites s rewrs =
257    merge_cs [s, csfrag_rewrites rewrs];
258
259
260fun CONGRUENCE_SIMP_QCONV relation (cs as (CS csdata)) ss =
261  let
262    (*build a connection between the preorders and =*)
263    val preorders = (#relations csdata);
264    val preorders = filter (fn p => not (same_const (extract_preorder_const p)
265                                                    boolSyntax.equality))
266                           preorders;
267    val preorder_eq_congs = map mk_eq_congproc preorders
268    val eq_congsTravrule = TRAVRULES
269      {relations=(#relations csdata),
270      congprocs=preorder_eq_congs,
271      weakenprocs=[]};
272    val traversedata = traversedata_for_ss ss;
273    val data = {rewriters= (#cong_reducer csdata)::
274          (map eq_reducer_wrapper (#rewriters traversedata)),
275          dprocs= (#dprocs csdata)@(map eq_reducer_wrapper (#dprocs traversedata)),
276          relation= relation, limit = #limit csdata,
277          travrules= merge_travrules ([eq_congsTravrule,#travrules traversedata]@(#travrules csdata))}
278  in
279    TRAVERSE data
280  end;
281
282
283fun CONGRUENCE_SIMP_CONV relation (cs as (CS csdata)) ss =
284  let
285    val qconv = CONGRUENCE_SIMP_QCONV relation cs ss
286    val preorder = find_relation relation (#relations csdata);
287    val refl = extract_preorder_refl preorder
288    fun conv thms tm = qconv thms tm handle _ => refl {Rinst=relation,arg=tm}
289  in
290    conv
291  end;
292
293
294val CONGRUENCE_EQ_SIMP_CONV = CONGRUENCE_SIMP_CONV ``$=``;
295
296
297fun CONGRUENCE_SIMP_RULE cs ss =
298  (fn thms =>
299    CONV_RULE (CONGRUENCE_EQ_SIMP_CONV cs ss thms));
300
301fun CONGRUENCE_SIMP_TAC cs ss =
302  (fn thms =>
303    CONV_TAC (CONGRUENCE_EQ_SIMP_CONV cs ss thms));
304
305
306fun ASM_CONGRUENCE_SIMP_TAC cs ss l = let
307  fun base thl (asms, gl) = let
308    val working = markerLib.LLABEL_RESOLVE thl asms
309  in
310    CONGRUENCE_SIMP_TAC cs ss working (asms, gl)
311  end
312in
313  markerLib.ABBRS_THEN base l
314end
315
316fun FULL_CONGRUENCE_SIMP_TAC cs ss l =
317       let fun drop n (asms,g) =
318         let val l = length asms
319             fun f asms =
320           MAP_EVERY ASSUME_TAC
321                                 (rev (fst (split_after (l-n) asms)))
322         in
323                 if (n > l) then STRUCT_ERR "congLib" ("drop", "Bad cut off number")
324           else POP_ASSUM_LIST f (asms,g)
325         end
326
327           (* differs only in that it doesn't call DISCARD_TAC *)
328           val STRIP_ASSUME_TAC' =
329         REPEAT_TCL STRIP_THM_THEN
330                    (fn th => FIRST [CONTR_TAC th, ACCEPT_TAC th,
331                                           ASSUME_TAC th])
332     fun simp_asm (t,l') = CONGRUENCE_SIMP_RULE cs ss (l'@l) t::l'
333     fun f asms =
334         MAP_EVERY STRIP_ASSUME_TAC' (foldl simp_asm [] asms)
335         THEN drop (length asms)
336       in
337         markerLib.ABBRS_THEN
338          (fn l => ASSUM_LIST f THEN ASM_CONGRUENCE_SIMP_TAC cs ss l) l
339       end
340
341end
342