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