1292934Sdimstructure decompilerLib :> decompilerLib = 2292934Sdimstruct 3353358Sdim 4353358Sdimopen HolKernel boolLib bossLib Parse; 5353358Sdim 6292934Sdimopen listTheory wordsTheory pred_setTheory arithmeticTheory wordsLib pairTheory; 7292934Sdimopen set_sepTheory progTheory helperLib addressTheory; 8292934Sdim 9292934Sdimstructure Parse = 10292934Sdimstruct 11292934Sdim open Parse 12292934Sdim val (Type, Term) = parse_from_grammars addressTheory.address_grammars 13321369Sdimend 14314564Sdim 15292934Sdim(* -------------------------------------------------------------------------- *) 16292934Sdim(* Decompilation stages: *) 17292934Sdim(* 1. derive SPEC theorem for each machine instruction, abbreviate code *) 18292934Sdim(* 2. extract control flow graph *) 19292934Sdim(* 3. for each code segment: *) 20292934Sdim(* a. compose SPEC theorems for one-pass through the code *) 21292934Sdim(* b. merge one-pass theorems into one theorem *) 22292934Sdim(* c. extract the function describing the code *) 23292934Sdim(* 4. store and return result of decompilation *) 24292934Sdim(* -------------------------------------------------------------------------- *) 25292934Sdim 26292934Sdim(* decompiler's memory *) 27314564Sdim 28292934Sdimval decompiler_memory = ref ([]:(string * (thm * int * int option)) list) 29314564Sdimval decompiler_finalise = ref (I:(thm * thm -> thm * thm)) 30353358Sdimval code_abbreviations = ref ([]:thm list); 31314564Sdimval abbreviate_code = ref false; 32360784Sdimval user_defined_modifier = ref (fn (name:string) => fn (th:thm) => th); 33314564Sdimval decompile_as_single_function = ref false; 34327952Sdim 35292934Sdimval decompiler_set_pc = ref ((fn y => fn th => fail()) :int -> thm -> thm); 36292934Sdim 37292934Sdimfun add_decompiled (name,th,code_len,code_exit) = 38292934Sdim (decompiler_memory := (name,(th,code_len,code_exit)) :: !decompiler_memory); 39292934Sdim 40292934Sdimfun get_decompiled name = 41292934Sdim snd (hd (filter (fn (x,y) => x = name) (!decompiler_memory))) 42292934Sdim handle _ => fail(); 43292934Sdim 44292934Sdimfun add_code_abbrev thms = (code_abbreviations := thms @ !code_abbreviations); 45314564Sdimfun set_abbreviate_code b = (abbreviate_code := b); 46314564Sdimfun get_abbreviate_code () = !abbreviate_code; 47314564Sdim 48292934Sdimfun add_modifier name f = let 49292934Sdim val current = !user_defined_modifier 50353358Sdim in user_defined_modifier := (fn x => if x = name then f else current x) end; 51292934Sdimfun remove_all_modifiers () = 52360784Sdim user_defined_modifier := (fn (name:string) => fn (th:thm) => th); 53360784Sdimfun modifier name th = (!user_defined_modifier) name th; 54360784Sdim 55314564Sdim 56314564Sdim(* general set-up *) 57360784Sdim 58360784Sdimval _ = map Parse.hide ["r0","r1","r2","r3","r4","r5","r6","r7","r8","r9", 59292934Sdim "r10","r11","r12","r13","r14","r15"]; 60344779Sdimval _ = set_echo 5; 61353358Sdim 62344779Sdim 63292934Sdim(* -------------------------------------------------------------------------- *) 64292934Sdim(* Various helper functions *) 65292934Sdim(* -------------------------------------------------------------------------- *) 66292934Sdim 67353358Sdimfun take n [] = [] 68353358Sdim | take n (x::xs) = if n = 0 then [] else x :: take (n-1) xs 69292934Sdim 70292934Sdimfun drop n [] = [] 71292934Sdim | drop n (x::xs) = if n = 0 then x::xs else drop (n-1) xs 72292934Sdim 73292934Sdimfun take_until p [] = [] 74353358Sdim | take_until p (x::xs) = if p x then [] else x:: take_until p xs 75292934Sdim 76292934Sdimfun diff xs ys = filter (fn x => not (mem x ys)) xs 77292934Sdimfun subset xs ys = (diff xs ys = []) 78292934Sdimfun same_set xs ys = subset xs ys andalso subset ys xs 79292934Sdimfun disjoint xs ys = diff xs ys = xs 80321369Sdim 81292934Sdimfun negate tm = dest_neg tm handle HOL_ERR e => mk_neg tm 82292934Sdimfun the (SOME x) = x | the NONE = fail() 83353358Sdim 84292934Sdimfun is_new_var v = 85353358Sdim (String.isPrefix "new@" o fst o dest_var) v handle HOL_ERR _ => false 86353358Sdimfun dest_new_var tm = if not (is_new_var tm) then fail() else let 87314564Sdim val (s,ty) = dest_var tm 88353358Sdim in mk_var(implode (drop 4 (explode s)), ty) end 89360784Sdim 90360784Sdimfun dest_tuple tm = 91353358Sdim let val (x,y) = pairSyntax.dest_pair tm in x :: dest_tuple y end 92353358Sdim handle HOL_ERR e => [tm]; 93353358Sdim 94360784Sdimfun mk_tuple_abs (v,tm) = 95353358Sdim if v = ``()`` then 96353358Sdim (subst [mk_var("x",type_of tm) |-> tm] 97353358Sdim (inst [``:'a``|->type_of tm] ``\():unit.x:'a``)) 98353358Sdim else pairSyntax.list_mk_pabs([v],tm) 99353358Sdim 100353358Sdimfun dest_sep_cond tm = 101353358Sdim if (fst o dest_const o fst o dest_comb) tm = "cond" 102353358Sdim then snd (dest_comb tm) else fail(); 103353358Sdim 104353358Sdimfun n_times 0 f x = x | n_times n f x = n_times (n-1) f (f x) 105314564Sdim 106360784Sdimfun replace_char c str = 107360784Sdim String.translate (fn x => if x = c then str else implode [x]); 108360784Sdim 109314564Sdimfun REPLACE_CONV th tm = let 110292934Sdim val th = SPEC_ALL th 111353358Sdim val (i,j) = match_term ((fst o dest_eq o concl) th) tm 112292934Sdim in INST i (INST_TYPE j th) end 113327952Sdim 114353358Sdim(* expands pairs 115353358Sdim ``(x,y,z) = f`` --> (x = FST f) /\ (y = FST (SND f)) /\ (z = ...) *) 116353358Sdimfun expand_conv tm = let 117327952Sdim val cc = RAND_CONV (REPLACE_CONV (GSYM pairTheory.PAIR)) 118327952Sdim val cc = cc THENC REPLACE_CONV pairTheory.PAIR_EQ 119292934Sdim val th = cc tm 120360784Sdim in CONV_RULE (RAND_CONV (RAND_CONV expand_conv)) th end 121360784Sdim handle HOL_ERR e => REFL tm 122360784Sdim 123344779Sdimfun list_mk_pair xs = pairSyntax.list_mk_pair xs handle HOL_ERR e => ``()`` 124353358Sdimfun list_dest_pair tm = let val (x,y) = pairSyntax.dest_pair tm 125353358Sdim in list_dest_pair x @ list_dest_pair y end handle HOL_ERR e => [tm] 126353358Sdim 127292934Sdimfun list_union [] xs = xs 128353358Sdim | list_union (y::ys) xs = 129353358Sdim if mem y xs then list_union ys xs else list_union ys (y::xs); 130353358Sdim 131353358Sdimfun append_lists [] = [] | append_lists (x::xs) = x @ append_lists xs 132292934Sdim 133292934Sdimval (no_tools:decompiler_tools) = let 134353358Sdim val no_jump = fn x => fail() 135314564Sdim val no_spec = fn x => fail() 136353358Sdim in (no_spec, no_jump, TRUTH, T) end 137344779Sdim 138292934Sdimval curr_tools = ref no_tools; 139292934Sdim 140292934Sdimfun set_tools tools = (curr_tools := tools); 141292934Sdimfun get_tools () = !curr_tools 142 143fun get_pc () = let val (_,_,_,x) = get_tools () in x end; 144fun get_status () = let val (_,_,x,_) = get_tools () in x end; 145 146fun get_output_list def = let 147 val tm = (concl o last o CONJUNCTS o SPEC_ALL) def 148 val (fm,tm) = dest_eq tm 149 val t = (tm2ftree) tm 150 fun ftree2res (FUN_VAL tm) = [tm] 151 | ftree2res (FUN_IF (tm,x,y)) = ftree2res x @ ftree2res y 152 | ftree2res (FUN_LET (tm,tn,x)) = ftree2res x 153 | ftree2res (FUN_COND (tm,x)) = ftree2res x 154 val res = filter (fn x => not (x = fm)) (ftree2res t) 155 val result = dest_tuple (hd res) 156 fun deprime x = mk_var(replace_char #"'" "" (fst (dest_var x)), type_of x) 157 handle HOL_ERR e => x 158 in pairSyntax.list_mk_pair(map deprime result) end; 159 160val GUARD_THM = 161 prove(``!m n x. GUARD n x = GUARD m x``, REWRITE_TAC [GUARD_def]); 162 163 164(* -------------------------------------------------------------------------- *) 165(* Implementation of STAGE 1 *) 166(* -------------------------------------------------------------------------- *) 167 168(* formatting *) 169 170val stack_terms = ([]):term list; 171 172fun DISCH_ALL_AS_SINGLE_IMP th = let 173 val th = RW [AND_IMP_INTRO] (DISCH_ALL th) 174 in if is_imp (concl th) then th else DISCH ``T`` th end 175 176fun replace_abbrev_vars tm = let 177 fun f v = v |-> mk_var((Substring.string o hd o tl o 178 Substring.tokens (fn x => x = #"@") o 179 Substring.full o fst o dest_var) v, type_of v) 180 handle HOL_ERR e => v |-> v 181 in subst (map f (free_vars tm)) tm end 182 183fun name_for_abbrev p tm = let 184 val x = get_sep_domain tm 185 in first (fn t => rator t = x) p |> rand |> dest_var |> fst end 186 handle HOL_ERR _ => 187 "v" ^ (int_to_string (Arbnum.toInt(numSyntax.dest_numeral(cdr (car tm))))) 188 handle HOL_ERR e => 189 if (fst (dest_const (car tm)) = "tT") handle HOL_ERR e => false then "k" else 190 if is_const (cdr (car tm)) andalso is_const(car (car tm)) 191 handle HOL_ERR e => false then 192 (to_lower o fst o dest_const o cdr o car) tm 193 else if can (match_term ``(f ((n2w n):'a word) (x:'c)):'d``) tm then 194 "r" ^ ((int_to_string o numSyntax.int_of_term o cdr o cdr o car) tm) 195 else 196 fst (dest_var (repeat cdr tm)) handle HOL_ERR e => 197 fst (dest_var (find_term is_var tm)) handle HOL_ERR e => 198 fst (dest_const (repeat car (get_sep_domain tm))); 199 200fun raw_abbreviate2 (var_name,y,tm) th = let 201 val y = mk_eq(mk_var(var_name,type_of y),y) 202 val cc = UNBETA_CONV tm 203 THENC (RAND_CONV) (fn t => GSYM (ASSUME y)) 204 THENC BETA_CONV 205 val th = CONV_RULE (RAND_CONV cc) th 206 in th end; 207 208fun raw_abbreviate (var_name,y,tm) th = let 209 val y = mk_eq(mk_var(var_name,type_of y),y) 210 val cc = UNBETA_CONV tm 211 THENC (RAND_CONV o RAND_CONV) (fn t => GSYM (ASSUME y)) 212 THENC BETA_CONV 213 val th = CONV_RULE (RAND_CONV cc) th 214 in th end; 215 216fun abbreviate (var_name,tm) th = raw_abbreviate (var_name,cdr tm,tm) th 217 218fun ABBREV_POSTS dont_abbrev_list prefix th = let 219 fun dont_abbrev tm = mem tm (dont_abbrev_list @ stack_terms) 220 fun next_abbrev p [] = fail() 221 | next_abbrev p (tm::xs) = 222 if (is_var (cdr tm) andalso 223 (name_for_abbrev p tm = fst (dest_var (cdr tm)))) 224 handle HOL_ERR e => false then next_abbrev p xs else 225 if (prefix ^ (name_for_abbrev p tm) = fst (dest_var (cdr tm))) 226 handle HOL_ERR e => false then next_abbrev p xs else 227 if can dest_sep_hide tm then next_abbrev p xs else 228 if dont_abbrev (car tm) then next_abbrev p xs else 229 (prefix ^ name_for_abbrev p tm,tm) 230 val (th,b) = let 231 val (_,p,_,q) = dest_spec (concl th) 232 val p = list_dest dest_star p 233 |> filter (fn tm => (is_var o rand) tm handle HOL_ERR _ => false) 234 val xs = list_dest dest_star q 235 val th = abbreviate (next_abbrev p xs) th 236 in (th,true) end handle HOL_ERR e => (th,false) handle Empty => (th,false) 237 in if b then ABBREV_POSTS dont_abbrev_list prefix th else th end; 238 239fun ABBREV_PRECOND prefix th = let 240 val th = RW [SPEC_MOVE_COND] (SIMP_RULE (bool_ss++sep_cond_ss) [] th) 241 val tm = (fst o dest_imp o concl) th 242 val v = mk_var(prefix^"cond",``:bool``) 243 val thx = SYM (BETA_CONV (mk_comb(mk_abs(v,v),tm))) 244 val th = CONV_RULE ((RATOR_CONV o RAND_CONV) (fn tm => thx)) th 245 val th = SIMP_RULE (bool_ss++sep_cond_ss) [] (RW [precond_def] (UNDISCH th)) 246 in th end handle HOL_ERR e => th handle Empty => th; 247 248fun ABBREV_STACK prefix th = let 249 val (_,p,_,q) = dest_spec (concl th) 250 val f = find_term (fn tm => mem (car tm) stack_terms 251 handle HOL_ERR _ => false) 252 val s_pre = f p 253 val s_post = f q 254 val xs = map (fn {redex=x1, residue=x2} => (x1,x2)) 255 (fst (match_term s_pre s_post)) 256 val th1 = CONV_RULE (UNBETA_CONV s_post) th 257 val ys = map (fn (x1,x2) => 258 mk_eq(mk_var(prefix ^ fst (dest_var x1), type_of x1),x2)) xs 259 val rw = map (GSYM o ASSUME) ys 260 val cs = map (fn th => fn tm => 261 if tm = fst (dest_eq (concl th)) then th else NO_CONV tm) rw 262 fun each [] = ALL_CONV | each (c::cs) = c ORELSEC each cs 263 val th1 = CONV_RULE (RAND_CONV (DEPTH_CONV (each cs)) THENC BETA_CONV) th1 264 in th1 end handle HOL_ERR _ => th 265 266fun ABBREV_ALL dont_abbrev_list prefix th = let 267 val th = ABBREV_POSTS dont_abbrev_list prefix th 268 val th = ABBREV_STACK prefix th 269 val th = ABBREV_PRECOND prefix th 270 in th end; 271 272fun ABBREV_CALL prefix th = let 273 val (_,_,_,q) = (dest_spec o concl) th 274 val (x,tm) = pairSyntax.dest_anylet q 275 val (x,y) = hd x 276 val ys = map (fn v => mk_var(prefix^(fst (dest_var v)),type_of v)) 277 (dest_tuple x) 278 val thi = ASSUME (mk_eq(pairSyntax.list_mk_pair ys, y)) 279 val thj = RW1 [LET_DEF] (GSYM thi) 280 val th = CONV_RULE (RAND_CONV (RAND_CONV (fn tm => thj))) (RW [LET_DEF] th) 281 val th = RW [FST,SND] (PairRules.PBETA_RULE (RW [LET_DEF] th)) 282 in ABBREV_PRECOND prefix th end 283 handle HOL_ERR e => ABBREV_PRECOND prefix th 284 handle Empty => ABBREV_PRECOND prefix th; 285 286fun UNABBREV_ALL th = let 287 fun remove_abbrev th = let 288 val th = CONV_RULE ((RATOR_CONV o RAND_CONV) expand_conv) th 289 val th = RW [GSYM AND_IMP_INTRO] th 290 val (x,y) = (dest_eq o fst o dest_imp o concl) th 291 in MP (INST [x|->y] th) (REFL y) end 292 handle HOL_ERR e => 293 UNDISCH (CONV_RULE ((RATOR_CONV o RAND_CONV) BETA_CONV) th) 294 handle HOL_ERR e => UNDISCH th 295 in repeat remove_abbrev (DISCH_ALL th) end; 296 297 298(* derive SPEC theorems *) 299 300fun pair_apply f ((th1,x1:int,x2:int option),NONE) = ((f th1,x1,x2),NONE) 301 | pair_apply f ((th1,x1,x2),SOME (th2,y1:int,y2:int option)) = 302 ((f th1,x1,x2),SOME (f th2,y1,y2)) 303 304fun jump_apply f NONE = NONE | jump_apply f (SOME x) = SOME (f x); 305 306fun pair_jump_apply (f:int->int) ((th1,x1:int,x2:int option),NONE) = 307 ((th1,x1,jump_apply f x2),NONE) 308 | pair_jump_apply f ((th1:thm,x1,x2),SOME (th2:thm,y1:int,y2:int option)) = 309 ((th1,x1,jump_apply f x2),SOME (th2,y1,jump_apply f y2)); 310 311fun introduce_guards thms = let 312 val pattern = (fst o dest_eq o concl o SPEC_ALL) cond_def 313(* 314 val (n,(th1,i1,j1),SOME (th2,i2,j2)) = el 8 res 315*) 316 fun intro (n,(th1,i1,j1),NONE) = (n,(th1,i1,j1),NONE) 317 | intro (n,(th1,i1,j1),SOME (th2,i2,j2)) = let 318 val t1 = cdr (find_term (can (match_term pattern)) (concl th1)) 319 val t2 = cdr (find_term (can (match_term pattern)) (concl th2)) 320 val h = RW [SPEC_MOVE_COND] o SIMP_RULE (bool_ss++sep_cond_ss) [] 321 val (th1,th2) = (h th1,h th2) 322 val tm1 = (mk_neg o fst o dest_imp o concl) th1 323 val tm2 = (fst o dest_imp o concl) th2 324 val lemma = 325 auto_prove "introduce_guards" (mk_eq(tm2,tm1),SIMP_TAC std_ss []) 326 val th2 = 327 CONV_RULE ((RATOR_CONV o RAND_CONV) (ONCE_REWRITE_CONV [lemma])) th2 328 val rw = SPEC (numSyntax.term_of_int n) GUARD_def 329 val f1 = 330 CONV_RULE ((RATOR_CONV o RAND_CONV) (PURE_ONCE_REWRITE_CONV [GSYM rw])) 331 val f2 = CONV_RULE ((RATOR_CONV o RAND_CONV o RAND_CONV) 332 (PURE_ONCE_REWRITE_CONV [GSYM rw])) 333 val (th1,th2) = if is_neg t1 then (f2 th1,f1 th2) else (f1 th1, f2 th2) 334 val h2 = RW [GSYM SPEC_MOVE_COND] 335 val (th1,th2) = (h2 th1,h2 th2) 336 in (n,(th1,i1,j1),SOME (th2,i2,j2)) end 337 val thms = map intro thms 338 in thms end 339 340fun derive_individual_specs tools (code:string list) = let 341 val (f,_,hide_th,pc) = tools 342 fun get_model_status_list th = 343 (map dest_sep_hide o list_dest dest_star o snd o dest_eq o concl) th 344 handle HOL_ERR e => [] 345 val dont_abbrev_list = pc :: get_model_status_list hide_th 346 val delete_spaces = (implode o filter (fn x => not(x = #" ")) o explode) 347 fun list_find name [] = fail () 348 | list_find name ((x,y)::xs) = if name = x then y else list_find name xs 349 fun get_specs (instruction,(n,ys)) = 350 if String.isPrefix "insert:" (delete_spaces instruction) then let 351 val name = delete_spaces instruction 352 val name = substring(name,7,length (explode name) - 7) 353 val (th,i,j) = list_find name (!decompiler_memory) 354 val th = RW [sidecond_def,hide_th,STAR_ASSOC] th 355 val th = ABBREV_CALL ("new@") th 356 val _ = echo 1 " (insert command)\n" 357 in (n+1,(ys @ [(n,(th,i,j),NONE)])) end 358 else let 359 val _ = echo 1 (" "^instruction^":") 360 val i = int_to_string n 361 val g = RW [precond_def] o ABBREV_ALL dont_abbrev_list ("new@") 362 val (x,y) = pair_apply g (f instruction) 363 val _ = echo 1 ".\n" 364 in (n+1,(ys @ [(n,x,y)])) end 365 val _ = echo 1 "\nDeriving theorems for individual instructions.\n" 366(* 367 val instruction = el 1 code 368 val ((th,_,_),_) = f instruction 369 val th = renamer th 370 val prefix = "foo@" 371*) 372 val res = snd (foldl get_specs (1,[]) code) 373 val res = introduce_guards res 374 fun calc_addresses i [] = [] 375 | calc_addresses i ((n:int,(th1:thm,l1,j1),y)::xs) = let 376 val (x,y) = pair_jump_apply (fn j => i+j) ((th1,l1,j1),y) 377 in (i,x,y) :: calc_addresses (i+l1) xs end 378 val res = calc_addresses 0 res 379 val _ = echo 1 "\n" 380 in res end; 381 382fun inst_pc_var tools thms = let 383 fun triple_apply f (y,(th1,x1:int,x2:int option),NONE) = 384 (y,(f y th1,x1,x2),NONE) 385 | triple_apply f (y,(th1,x1,x2),SOME (th2,y1:int,y2:int option)) = 386 (y,(f y th1,x1,x2),SOME (f y th2,y1,y2)) 387 val i = [mk_var("pc",``:word32``) |-> mk_var("p",``:word32``), 388 mk_var("pc",``:word64``) |-> mk_var("p",``:word64``), 389 mk_var("eip",``:word32``) |-> mk_var("p",``:word32``), 390 mk_var("rip",``:word64``) |-> mk_var("p",``:word64``)] 391 val (_,_,_,pc) = tools 392 val ty = (hd o snd o dest_type o type_of) pc 393 fun f y th = (!decompiler_set_pc) y th handle HOL_ERR _ => let 394 val aa = (hd o tl o snd o dest_type) ty 395 val th = INST i th 396 val (_,p,_,_) = dest_spec (concl th) 397 val pattern = inst [``:'a``|->aa] ``(p:'a word) + n2w n`` 398 val new_p = 399 subst [mk_var("n",``:num``)|-> numSyntax.mk_numeral (Arbnum.fromInt y)] 400 pattern 401 val th = INST [mk_var("p",type_of new_p)|->new_p] th 402 val (_,_,_,q) = dest_spec (concl th) 403 val tm = find_term (fn tm => car tm = pc handle HOL_ERR e => false) q 404 val cc = 405 SIMP_CONV std_ss [word_arith_lemma1,word_arith_lemma3,word_arith_lemma4] 406 val th = CONV_RULE ((RATOR_CONV o RAND_CONV) cc) th 407 val thi = QCONV cc tm 408 in PURE_REWRITE_RULE [thi,WORD_ADD_0] th end; 409 in map (triple_apply f) thms end 410 411fun UNABBREV_CODE_RULE th = let 412 val rw = (!code_abbreviations) 413 val c = REWRITE_CONV rw THENC 414 SIMP_CONV std_ss [word_arith_lemma1] THENC 415 REWRITE_CONV [INSERT_UNION_EQ,UNION_EMPTY] 416 val th = CONV_RULE ((RATOR_CONV o RAND_CONV) c) th 417 in th end; 418 419val ABBBREV_CODE_LEMMA = prove( 420 ``!a (x :('a, 'b, 'c) processor) p c q. 421 (a ==> SPEC x p c q) ==> !d. c SUBSET d ==> a ==> SPEC x p d q``, 422 REPEAT STRIP_TAC THEN RES_TAC THEN IMP_RES_TAC SPEC_SUBSET_CODE); 423 424fun abbreviate_code name thms = let 425 fun extract_code (_,(th,_,_),_) = 426 let val (_,_,c,_) = dest_spec (concl th) in c end 427 val cs = map extract_code thms 428 val ty = (hd o snd o dest_type o type_of o hd) cs 429 val tm = foldr pred_setSyntax.mk_union (pred_setSyntax.mk_empty ty) cs 430 val cth = QCONV (PURE_REWRITE_CONV [INSERT_UNION_EQ,UNION_EMPTY]) tm 431 val c = (cdr o concl) cth 432 val (_,(th,_,_),_) = hd thms 433 val (m,_,_,_) = dest_spec (concl th) 434 val model_name = (to_lower o implode o take_until (fn x => x = #"_") o 435 explode o fst o dest_const) m 436 val x = list_mk_pair (free_vars c) 437 val def_name = name ^ "_" ^ model_name 438 val v = mk_var(def_name,type_of(mk_pabs(x,c))) 439 val code_def = new_definition(def_name ^ "_def",mk_eq(mk_comb(v,x),c)) 440 val _ = add_code_abbrev [code_def] 441 fun triple_apply f (y,(th1,x1:int,x2:int option),NONE) = 442 (y,(f th1,x1,x2),NONE) 443 | triple_apply f (y,(th1,x1,x2),SOME (th2,y1:int,y2:int option)) = 444 (y,(f th1,x1,x2),SOME (f th2,y1,y2)) 445 val code_thm = CONV_RULE (RAND_CONV (fn _ => GSYM cth)) (SPEC_ALL code_def) 446 fun foo th = let 447 val thi = MATCH_MP ABBBREV_CODE_LEMMA (DISCH_ALL_AS_SINGLE_IMP th) 448 val thi = SPEC ((fst o dest_eq o concl o SPEC_ALL) code_def) thi 449 val goal = (fst o dest_imp o concl) thi 450 val lemma = auto_prove "abbreviate_code" (goal, 451 REPEAT (REWRITE_TAC [code_thm,SUBSET_DEF,IN_UNION] THEN REPEAT STRIP_TAC 452 THEN ASM_REWRITE_TAC [] THEN (fn _ => fail())) 453 THEN REWRITE_TAC [EMPTY_SUBSET] 454 THEN REWRITE_TAC [SUBSET_DEF,IN_INSERT,IN_UNION,NOT_IN_EMPTY,code_def] 455 THEN REPEAT STRIP_TAC THEN ASM_SIMP_TAC std_ss []) 456 val thi = 457 UNDISCH_ALL (PURE_REWRITE_RULE [GSYM AND_IMP_INTRO] (MP thi lemma)) 458 in thi end 459 val thms = map (triple_apply foo) thms 460 in thms end 461 462fun stage_1 name tools code = 463 let 464 val thms = derive_individual_specs tools code 465 val thms = inst_pc_var tools thms 466 val thms = abbreviate_code name thms 467 in 468 thms 469 end; 470 471 472(* -------------------------------------------------------------------------- *) 473(* Implementation of STAGE 2 *) 474(* -------------------------------------------------------------------------- *) 475 476fun extract_graph thms = let 477 fun extract_jumps (i,(_,_,j),NONE) = [(i,j)] 478 | extract_jumps (i,(_,_,j),SOME (_,_,k)) = [(i,j),(i,k)] 479 val jumps = append_lists (map extract_jumps thms) 480 in jumps end; 481 482fun all_distinct [] = [] 483 | all_distinct (x::xs) = x :: all_distinct (filter (fn z => not (x = z)) xs) 484 485fun drop_until P [] = [] 486 | drop_until P (x::xs) = if P x then x::xs else drop_until P xs 487 488fun jumps2edges jumps = let 489 fun h (i,NONE) = [] 490 | h (i,SOME j) = [(i,j)] 491 in append_lists (map h jumps) end; 492 493fun extract_loops jumps = let 494 (* find all possible paths *) 495 val edges = jumps2edges jumps 496 fun all_paths_from edges i prefix = let 497 fun f [] = [] 498 | f ((k,j)::xs) = if i = k then j :: f xs else f xs 499 val next = all_distinct (f edges) 500 val prefix = prefix @ [i] 501 val xs = map (fn x => if mem x prefix then [prefix @ [x]] else 502 all_paths_from edges x prefix) next 503 val xs = if xs = [] then [[prefix]] else xs 504 in append_lists xs end 505 val paths = all_paths_from edges 0 [] 506 (* get looping points *) 507 fun is_loop xs = mem (last xs) (butlast xs) 508 val loops = all_distinct (map last (filter is_loop paths)) 509 (* find loop bodies and tails *) 510 fun loop_body_tail i = let 511 val bodies = filter (fn xs => last xs = i) paths 512 val bodies = filter is_loop bodies 513 val bodies = map (drop_until (fn x => x = i) o butlast) bodies 514 val bodies = all_distinct (append_lists bodies) 515 val tails = filter (fn xs => mem i xs andalso not (last xs = i)) paths 516 val tails = map (drop_until (fn x => x = i)) tails 517 in (i,bodies,tails) end 518 val summaries = map loop_body_tail loops 519 (* clean loop tails *) 520 fun clean_tails (i,xs,tails) = let 521 val tails = map (drop_until (fn x => not (mem x xs))) tails 522 val tails = filter (fn xs => not (xs = [])) tails 523 in (i,xs,tails) end 524 val zs = map clean_tails summaries 525 (* merge combined loops *) 526 val zs = map (fn (x,y,z) => ([x],y,z)) zs 527 fun find_and_merge zs = let 528 val ls = append_lists (map (fn (x,y,z) => x) zs) 529 val qs = map (fn (x,y,z) => (x,y,map hd z)) zs 530 fun f ys = filter (fn x => mem x ls andalso (not (mem x ys))) 531 val qs = map (fn (x,y,z) => (x,all_distinct (f x y @ f x z))) qs 532 fun cross [] ys = [] 533 | cross (x::xs) ys = map (fn y => (x,y)) ys @ cross xs ys 534 val edges = append_lists (map (fn (x,y) => cross x y) qs) 535 val paths = map (fn i => all_paths_from edges i []) ls 536 val goals = map (fn (x,y) => (y,x)) edges 537 fun sat_goal ((i,j),path) = (hd path = i) andalso (mem j (tl path)) 538 val (i,j) = fst (hd (filter sat_goal (cross goals (append_lists paths)))) 539 val (p1,q1,x1) = hd (filter (fn (x,y,z) => mem i x) zs) 540 val (p2,q2,x2) = hd (filter (fn (x,y,z) => mem j x) zs) 541 val (p,q,x) = (p1 @ p2, all_distinct (q1 @ q2), x1 @ x2) 542 val zs = 543 (p,q,x) :: filter (fn (x,y,z) => not (mem i x) andalso not (mem j x)) zs 544 val zs = map clean_tails zs 545 in zs end 546 val zs = repeat find_and_merge zs 547 (* attempt to find common exit point *) 548 fun mem_all x [] = true 549 | mem_all x (xs::xss) = mem x xs andalso mem_all x xss 550 fun find_exit_points (x,y,z) = let 551 val q = hd (filter (fn x => mem_all x (tl z)) (hd z)) 552 in (x,[q]) end handle Empty => (x,all_distinct (map hd z)) 553 val zs = map find_exit_points zs 554 (* finalise *) 555 val exit = (all_distinct o map last o filter (not o is_loop)) paths 556 val zero = ([0],exit) 557 val zs = if filter (fn (x,y) => mem 0 x andalso subset exit y) zs = [] 558 then zs @ [zero] 559 else zs 560 fun list_before x y [] = true 561 | list_before x y (z::zs) = if z = y then false else 562 if z = x then true else list_before x y zs 563 fun compare (xs,_) (ys,_) = let 564 val x = hd xs 565 val y = hd ys 566 val p = hd (filter (fn xs => mem x xs andalso mem y xs) paths) 567 in not (list_before x y p) end handle Empty => false 568 val loops = sort compare zs 569 (* sort internal *) 570 val int_sort = sort (fn x => fn (y:int) => x <= y) 571 val loops = map (fn (xs,ys) => (int_sort xs, int_sort ys)) loops 572 (* deal with option to return result as a single function *) 573 val loops = if not (!decompile_as_single_function) then loops else let 574 val entry = all_distinct (append_lists (map fst loops)) 575 val exit = diff (all_distinct (append_lists (map snd loops))) entry 576 in [(sort (fn x => fn y => (x <= y)) entry,exit)] end 577 (* TODO: final states should still be optimised... *) 578 in loops end; 579 580fun stage_12 name tools code = 581 let 582 val thms = stage_1 name tools code 583 val jumps = extract_graph thms 584 val loops = extract_loops jumps 585 in 586 (thms, loops) 587 end; 588 589 590(* -------------------------------------------------------------------------- *) 591(* Implementation of STAGE 3 *) 592(* -------------------------------------------------------------------------- *) 593 594(* STAGE 3, part a ---------------------------------------------------------- *) 595 596local val varname_counter = ref 1 in 597 fun varname_reset () = (varname_counter := 1); 598 fun varname_next () = let 599 val v = !varname_counter 600 val _ = (varname_counter := v+1) 601 in v end 602end; 603 604(* functions for composing SPEC theorems *) 605 606fun replace_new_vars v th = let 607 fun mk_new_var prefix v = let 608 val (n,ty) = dest_var v 609 val _ = if String.isPrefix "new@" n then () else fail() 610 in mk_var (prefix ^ "@" ^ (implode o drop 4 o explode) n, ty) end 611 fun rename_new tm = 612 if is_comb tm 613 then (RATOR_CONV rename_new THENC RAND_CONV rename_new) tm 614 else if not (is_abs tm) 615 then ALL_CONV tm 616 else let 617 val (x,y) = dest_abs tm 618 val conv = ALPHA_CONV (mk_new_var v x) handle HOL_ERR e => ALL_CONV 619 in (conv THENC ABS_CONV rename_new) tm end 620 val th = GEN_ALL (DISCH_ALL th) 621 val th = CONV_RULE rename_new th 622 val th = UNDISCH_ALL (SPEC_ALL th) 623 in th end; 624 625fun SPEC_COMPOSE th1 th2 = let 626 (* replace "new@..." variables with fresh numbered variables *) 627 val th2a = replace_new_vars ("s" ^ int_to_string (varname_next ())) th2 628 in SPEC_COMPOSE_RULE [th1,th2a] end; 629 630fun number_GUARD (x,y,z) = let 631 val rw = SPEC (numSyntax.term_of_int (varname_next ())) GUARD_THM 632 fun f (th1,y1,y2) = (RW1[rw]th1,y1,y2) 633 fun apply_option g NONE = NONE 634 | apply_option g (SOME x) = SOME (g x) 635 in (x,f y,apply_option f z) end; 636 637(* multi-entry/exit preformatting *) 638 639fun format_for_multi_entry entry thms = let 640 val _ = if length entry = 1 then fail() else () 641 val pc_tm = get_pc() 642 val pos = mk_var("pos",``:num``) 643 val mk_num = numSyntax.mk_numeral o Arbnum.fromInt 644 fun mk_pos i = 645 subst [mk_var("n",``:num``) |-> mk_num i] ``p + (n2w n):word32`` 646 fun foo [] n = [] | foo (y::ys) n = n :: foo ys (n+1) 647 val xs = zip (map mk_num (foo entry 0)) (map mk_pos entry) 648 fun mk [] = fail() 649 | mk [(x,y)] = y 650 | mk ((x,y)::xs) = mk_cond(mk_eq(pos,x),y,mk xs) 651 val tm = mk xs 652 val case_list = map (fn (x,y) => mk_eq(pos,x)) xs 653 val format = 654 mk_imp(``GUARD 0 (pos = k:num)``, 655 mk_eq(mk_comb(pc_tm,mk_var("t1",``:word32``)), 656 mk_comb(pc_tm,mk_var("t2",``:word32``)))) 657 val format = subst [``t2:word32``|->tm] format 658 fun mk_sub (x,y) = subst [``k:num``|->x, ``t1:word32``|->y] format 659 fun mk_goals [] rest = fail() 660 | mk_goals [(x,y)] rest = 661 [mk_conj(mk_imp(rest,snd (dest_imp (mk_sub (x,y)))),mk_sub (x,y))] 662 | mk_goals ((x,y)::xs) rest = let 663 val xy = mk_sub (x,y) 664 val r = mk_neg((cdr o car) xy) 665 in mk_conj(mk_imp(rest,xy),xy) :: mk_goals xs (mk_conj(rest,r)) end 666 val goals = mk_goals xs T 667 fun two_conj th = let 668 val xs = CONJUNCTS th 669 in if length xs = 1 then (hd xs, hd xs) else (el 1 xs, el 2 xs) end 670 val ys = 671 map (fn goal => (two_conj o RW[AND_IMP_INTRO,GSYM CONJ_ASSOC,WORD_ADD_0]) 672 (prove(goal,SIMP_TAC std_ss [GUARD_def]))) goals 673 val posts = map snd ys 674 val pres = map fst ys 675 val posts = 676 map (RW [GUARD_def] o INST [pos|->mk_var("s10000@pos",type_of pos)]) posts 677 fun RW_CONV [] tm = NO_CONV tm 678 | RW_CONV (th::xs) tm = 679 if fst (dest_eq (concl th)) = tm then th else RW_CONV xs tm 680 handle HOL_ERR _ => NO_CONV tm 681 fun process th = let 682 val th = CONV_RULE (PRE_CONV (DEPTH_CONV (RW_CONV (map UNDISCH pres)))) th 683 val th = CONV_RULE (POST_CONV (DEPTH_CONV (RW_CONV (map UNDISCH posts)))) th 684 val th = UNDISCH (DISCH_ALL_AS_SINGLE_IMP th) 685 in th end 686 fun apply f (k,(th1,i1,j1),NONE) = (k,(f th1,i1,j1),NONE) 687 | apply f (k,(th1,i1,j1),SOME (th2,i2,j2)) = 688 (k,(f th1,i1,j1),SOME (f th2,i2,j2)) 689 val thms = map (apply process) thms 690 in (case_list,thms) end handle HOL_ERR _ => ([],thms); 691 692(* functions for deriving one-pass theorems *) 693 694datatype mc_tree = 695 LEAF of thm * int 696 | SEQ of term list * mc_tree 697 | BRANCH of term * mc_tree * mc_tree; 698 699fun basic_find_composition th1 (th2,l2,j2) = let 700 val th1 = modifier "pre" th1 701 val th2 = modifier "pre" th2 702 val th = remove_primes (SPEC_COMPOSE th1 th2) handle HOL_ERR e => 703 remove_primes (SPEC_COMPOSE th1 (UNABBREV_ALL th2)) 704 val th = modifier "post" th 705 val th = RW [WORD_CMP_NORMALISE] th 706 val th = RW [GSYM WORD_NOT_LOWER, GSYM WORD_NOT_LESS] th 707 fun h x = (fst o dest_eq) x handle e => (fst o dest_abs o car) x 708 fun f [] ys = ys | f (x::xs) ys = f xs (h x :: ys handle e => ys) 709 val th2_hyps = f (hyp th2) [] 710 fun g tm = mem (h tm) th2_hyps handle e => false 711 val lets = filter g (hyp th) 712 in ((th,l2,j2),lets) end 713 714fun find_cond_composition th1 NONE = fail() 715 | find_cond_composition th1 (SOME (th2,l2,j2)) = let 716 val th = RW [SPEC_MOVE_COND] th2 717 val th = if concl th = T then fail() else th 718 val th = if not (is_imp (concl th)) then th else 719 CONV_RULE 720 ((RATOR_CONV o RAND_CONV) 721 (ONCE_REWRITE_CONV [GSYM CONTAINER_def])) th 722 val th = RW [GSYM SPEC_MOVE_COND] th 723 val ((th,l,j),lets) = basic_find_composition th1 (th,l2,j2) 724 val th = SIMP_RULE (bool_ss++sep_cond_ss) [SEP_CLAUSES] th 725 val th = 726 SIMP_RULE std_ss [SPEC_MOVE_COND,GSYM AND_IMP_INTRO,SEP_EXISTS_COND] th 727 fun imps tm xs = 728 let val (x,y) = dest_imp tm in imps y (x::xs) end handle e => xs 729 fun is_CONTAINER tm = 730 (fst o dest_const o car) tm = "CONTAINER" handle e => false 731 val xs = filter is_CONTAINER (imps (concl th) []) 732 val th = RW [GSYM SPEC_MOVE_COND,CONTAINER_def] th 733 in let val cond = snd (dest_comb (hd xs)) in 734 let val cond = dest_neg cond in (cond,(th,l,j)) end 735 handle e => (mk_neg cond,(th,l,j)) end 736 handle e => (``F:bool``,(th,l,j)) end; 737 738fun remove_guard tm = 739 (cdr o concl o REWRITE_CONV [GUARD_def]) tm handle UNCHANGED => tm; 740 741fun find_first i [] = fail() 742 | find_first i ((x,y,z)::xs) = if i = x then (x,y,z) else find_first i xs 743 744fun tree_composition (th,i:int,thms,entry,exit,conds,firstTime) = 745 if mem i entry andalso not firstTime then LEAF (th,i) else 746 if mem i exit then LEAF (th,i) else let 747 val (_,thi1,thi2) = number_GUARD (find_first i thms) 748 in let (* try composing second branch *) 749 val (cond,(th2,_,i2)) = find_cond_composition th thi2 750 val cond' = remove_guard cond 751 in if mem (negate cond') conds 752 then (* case: only second branch possible *) 753 tree_composition (th2,the i2,thms,entry,exit,conds,false) 754 else if mem cond' conds then fail() 755 else (* case: both branches possible *) let 756 val ((th1,_,i1),lets) = basic_find_composition th thi1 757 val t1 = tree_composition 758 (th1,the i1,thms,entry,exit,cond'::conds,false) 759 val t2 = tree_composition 760 (th2,the i2,thms,entry,exit,negate cond'::conds,false) 761 val t1 = if length lets = 0 then t1 else SEQ (lets,t1) 762 in BRANCH (cond,t1,t2) end end 763 handle e => (* case: only first branch possible *) let 764 val ((th,_,i),lets) = basic_find_composition th thi1 765 val result = tree_composition (th,the i,thms,entry,exit,conds,false) 766 in if length lets = 0 then result else SEQ (lets,result) end end 767 768fun map_spectree f (LEAF (thm,i)) = LEAF (f thm,i) 769 | map_spectree f (SEQ (x,t)) = SEQ(x, map_spectree f t) 770 | map_spectree f (BRANCH (j,t1,t2)) = 771 BRANCH (j, map_spectree f t1, map_spectree f t2) 772 773fun merge_entry_points [] ts = hd ts 774 | merge_entry_points [x] ts = hd ts 775 | merge_entry_points (x::xs) ts = let 776 val t1 = merge_entry_points xs (tl ts) 777 in BRANCH (mk_comb(``GUARD 0``,x), hd ts, t1) end 778 779fun generate_spectree thms (entry,exit) = let 780 val _ = varname_reset () 781 val (_,(th,_,_),_) = hd thms 782 val hide_th = get_status() 783 fun apply_to_th f (i,(th,k,l),NONE) = (i,(f th,k,l),NONE) 784 | apply_to_th f (i,(th,k,l),SOME (th2,k2,l2)) = 785 (i,(f th,k,l),SOME (f th2,k2,l2)) 786 val thms = map (apply_to_th (RW [hide_th])) thms 787 val (case_list,thms) = format_for_multi_entry entry thms 788 val (_,(th,_,_),_) = hd thms 789 val (m,_,_,_) = dest_spec (concl th) 790 val (default_th,is,conds,firstTime) = 791 (Q.SPECL [`emp`,`{}`] (ISPEC m SPEC_REFL),entry,[]:term list,true) 792 val i = hd is 793 val _ = echo 1 "Composing," 794 val ts = map (fn i => let 795 val th = modifier ("shape " ^ int_to_string i) default_th 796 val t = tree_composition (th,i,thms,entry,exit,conds,firstTime) 797 in (i,t) end) is 798 val t = merge_entry_points case_list (map snd ts) 799 val t = if not (is_eq (concl (SPEC_ALL hide_th))) then t 800 else map_spectree (HIDE_STATUS_RULE true hide_th) t 801 val t = map_spectree (modifier "spec") t 802 in t end; 803 804(* 805val in_post = true 806fun spectree_leaves (LEAF (thm,i)) = [thm] 807 | spectree_leaves (SEQ (x,t)) = spectree_leaves t 808 | spectree_leaves (BRANCH (j,t1,t2)) = spectree_leaves t1 @ spectree_leaves t2 809val th = el 2 (spectree_leaves t) 810*) 811 812 813(* STAGE 3, part b ---------------------------------------------------------- *) 814 815(* merge spectree theorems *) 816 817fun strip_tag v = let 818 val vs = (drop_until (fn x => x = #"@") o explode o fst o dest_var) v 819 in if vs = [] then (fst o dest_var) v else implode (tl vs) end 820 821fun read_tag v = let 822 val xs = (explode o fst o dest_var) v 823 val vs = take_until (fn x => x = #"@") xs 824 in if length vs = length xs then "" else implode vs end 825 826fun ABBREV_NEW th = let 827 val pc = get_pc () 828 val ty = (hd o snd o dest_type o type_of) pc 829 val tm = 830 find_term (can (match_term (mk_comb(pc,genvar(ty))))) (cdr (concl th)) 831 val th = abbreviate ("new@p",tm) th 832 val ws = (filter (not o is_new_var) o free_vars o cdr o concl) th 833 fun one(v,th) = raw_abbreviate2 ("new@" ^ strip_tag v,v,v) th 834 val th = foldr one th ws 835 val th = 836 UNDISCH (RW [SPEC_MOVE_COND,AND_IMP_INTRO,GSYM CONJ_ASSOC] (DISCH_ALL th)) 837 in th end 838 839fun remove_tags tm = 840 subst (map (fn v => v |-> mk_var(strip_tag v,type_of v)) (free_vars tm)) tm 841 842fun list_dest_sep_exists tm = let 843 val vs = list_dest dest_sep_exists tm 844 in (butlast vs, last vs) end; 845 846fun prepare_sep_disj_posts th1 th2 = let 847 val (_,_,_,q1) = dest_spec (concl th1) 848 val (_,_,_,q2) = dest_spec (concl th2) 849 in if can dest_sep_disj q1 orelse can dest_sep_disj q2 then let 850 val th1 = if can dest_sep_disj q2 then 851 SPEC (snd (dest_sep_disj q2)) (MATCH_MP SPEC_ADD_DISJ th1) 852 else th1 853 val th2 = if can dest_sep_disj q1 then 854 SPEC (snd (dest_sep_disj q1)) (MATCH_MP SPEC_ADD_DISJ th2) 855 else th2 856 val f = 857 RW [SEP_CLAUSES] o 858 CONV_RULE ((RAND_CONV o RAND_CONV) 859 (SIMP_CONV std_ss [AC SEP_DISJ_ASSOC SEP_DISJ_COMM])) o 860 RW [SEP_DISJ_ASSOC] 861 val th1 = f th1 862 val th2 = f th2 863 in (th1,th2) end 864 else (th1,th2) end; 865 866val merge_mem = ref (T,TRUTH,TRUTH); 867(* 868val (guard,th1,th2) = (!merge_mem); 869*) 870 871fun MERGE guard th1 th2 = let 872 (* fill in preconditions *) 873 val th1 = remove_primes th1 874 val th2 = remove_primes th2 875 val p = get_pc () 876 val (_,p1,_,q1) = dest_spec (concl th1) 877 val (_,p2,_,q2) = dest_spec (concl th2) 878 val (qs1,q1) = list_dest_sep_exists q1 879 val (qs2,q2) = list_dest_sep_exists q2 880 fun fst_sep_disj tm = fst (dest_sep_disj tm) handle HOL_ERR _ => tm 881 val xs1 = filter (fn x => not (p = get_sep_domain x)) 882 (list_dest dest_star (fst_sep_disj q1)) 883 val xs2 = filter (fn x => not (p = get_sep_domain x)) 884 (list_dest dest_star (fst_sep_disj q2)) 885 val xs1 = map remove_tags xs1 886 val xs2 = map remove_tags xs2 887 val zs1 = map get_sep_domain xs1 888 val zs2 = map get_sep_domain xs2 889 val ys1 = filter (fn x => not (mem (get_sep_domain x) zs1)) xs2 890 val ys2 = filter (fn x => not (mem (get_sep_domain x) zs2)) xs1 891 val th1 = SPEC (list_mk_star ys1 (type_of p1)) (MATCH_MP SPEC_FRAME th1) 892 val th2 = SPEC (list_mk_star ys2 (type_of p2)) (MATCH_MP SPEC_FRAME th2) 893 val th1 = SIMP_RULE std_ss [SEP_CLAUSES,STAR_ASSOC] th1 894 val th2 = SIMP_RULE std_ss [SEP_CLAUSES,STAR_ASSOC] th2 895 (* unhide relevant preconditions *) 896 val (_,p1,_,q1) = dest_spec (concl th1) 897 val (_,p2,_,q2) = dest_spec (concl th2) 898 val (ps1,p1) = list_dest_sep_exists p1 899 val (ps2,p2) = list_dest_sep_exists p2 900 val xs1 = filter (fn x => not (p = get_sep_domain x)) (list_dest dest_star p1) 901 val xs2 = filter (fn x => not (p = get_sep_domain x)) (list_dest dest_star p2) 902 val ys1 = map dest_sep_hide (filter (can dest_sep_hide) xs1) 903 val ys2 = map dest_sep_hide (filter (can dest_sep_hide) xs2) 904 val zs1 = (filter (not o can dest_sep_hide) xs1) 905 val zs2 = (filter (not o can dest_sep_hide) xs2) 906 val qs1 = filter (fn x => mem (car x) ys1 handle HOL_ERR _ => false) zs2 907 val qs2 = filter (fn x => mem (car x) ys2 handle HOL_ERR _ => false) zs1 908 val th1 = foldr (uncurry UNHIDE_PRE_RULE) th1 qs1 909 val th2 = foldr (uncurry UNHIDE_PRE_RULE) th2 qs2 910 (* hide relevant postconditions *) 911 val (_,p1,_,q1) = dest_spec (concl th1) 912 val (_,p2,_,q2) = dest_spec (concl th2) 913 val (qs1,q1) = list_dest_sep_exists q1 914 val (qs2,q2) = list_dest_sep_exists q2 915 val xs1 = filter (fn x => not (p = get_sep_domain x)) 916 (list_dest dest_star (fst_sep_disj q1)) 917 val xs2 = filter (fn x => not (p = get_sep_domain x)) 918 (list_dest dest_star (fst_sep_disj q2)) 919 val ys1 = map dest_sep_hide (filter (can dest_sep_hide) xs1) 920 val ys2 = map dest_sep_hide (filter (can dest_sep_hide) xs2) 921 fun safe_car tm = car tm handle HOL_ERR _ => tm 922 val zs1 = map safe_car (filter (not o can dest_sep_hide) xs1) 923 val zs2 = map safe_car (filter (not o can dest_sep_hide) xs2) 924 val qs1 = filter (fn x => mem x ys1) zs2 925 val qs2 = filter (fn x => mem x ys2) zs1 926 val th1 = foldr (uncurry HIDE_POST_RULE) th1 qs2 927 val th2 = foldr (uncurry HIDE_POST_RULE) th2 qs1 928 (* abbreviate posts *) 929 val f = CONV_RULE (PRE_CONV (SIMP_CONV (bool_ss++star_ss) []) THENC 930 POST_CONV (SIMP_CONV (bool_ss++star_ss) []) THENC 931 REWRITE_CONV [STAR_ASSOC]) 932 val th1 = f (ABBREV_NEW th1) 933 val th2 = f (ABBREV_NEW th2) 934 (* do the merge *) 935 fun g x = PURE_REWRITE_RULE [AND_IMP_INTRO] o DISCH x o DISCH_ALL 936 val (th1,th2) = prepare_sep_disj_posts th1 th2 937 val th = MATCH_MP SPEC_COMBINE (g guard th1) 938 val th = MATCH_MP th (g (mk_neg guard) th2) 939 val th = UNDISCH (RW [UNION_IDEMPOT] th) 940 val th = remove_primes th 941 in th end handle HOL_ERR e => let 942 val _ = (merge_mem := (guard,th1,th2)) 943 val th1 = DISCH_ALL th1 944 val th2 = DISCH_ALL th2 945 val _ = print ("\n\nval guard = ``"^ term_to_string guard ^"``;\n\n") 946 val _ = print ("\n\nval th1 = mk_thm([],``"^ term_to_string (concl th1) ^ 947 "``);\n\n") 948 val _ = print ("\n\nval th2 = mk_thm([],``"^ term_to_string (concl th2) ^ 949 "``);\n\n") 950 in raise HOL_ERR e end; 951 952fun merge_spectree_thm (LEAF (th,i)) = let 953 val th = SIMP_RULE (bool_ss++sep_cond_ss) [SEP_EXISTS_COND] th 954 val th = UNDISCH (RW [SPEC_MOVE_COND,AND_IMP_INTRO] (DISCH_ALL th)) 955 in (th,LEAF (TRUTH,i)) end 956 | merge_spectree_thm (SEQ (tms,t)) = let 957 val (th,t) = merge_spectree_thm t 958 in (th,SEQ (tms,t)) end 959 | merge_spectree_thm (BRANCH (guard,t1,t2)) = let 960 val (th1,t1') = merge_spectree_thm t1 961 val (th2,t2') = merge_spectree_thm t2 962 val th = MERGE guard th1 th2 963 in (th,BRANCH (guard,t1',t2')) end 964 965fun merge_spectree name t = let 966 val _ = echo 1 " merging cases," 967 val (th,_) = merge_spectree_thm t 968 val th = MERGE ``T`` th th 969 val th = UNDISCH_ALL (remove_primes (DISCH_ALL th)) 970 in th end 971 972 973(* STAGE 3, part c ---------------------------------------------------------- *) 974 975(* clean the theorem *) 976 977fun tagged_var_to_num v = let 978 fun drop_until p [] = [] 979 | drop_until p (x::xs) = if p x then x::xs else drop_until p xs 980 val xs = (take_until (fn x => x = #"@") o explode o fst o dest_var) v 981 val xs = 982 drop_until 983 (fn x => mem x [#"0",#"1",#"2",#"3",#"4",#"5",#"6",#"7",#"8",#"9"]) xs 984 val s = implode xs 985 val s = if s = "" then "100000" else s 986 in string_to_int s end 987 988val GUARD_T = prove(``!x. x = (x = GUARD 0 T)``,REWRITE_TAC [GUARD_def]) 989val GUARD_F = prove(``!x. ~x = (x = GUARD 0 F)``,REWRITE_TAC [GUARD_def]) 990 991fun init_clean th = let 992 fun side2guard_conv tm = 993 if not (can (match_term ``(\x.x:bool) y``) tm) 994 then NO_CONV tm else let 995 val v = 996 (numSyntax.term_of_int o tagged_var_to_num o fst o dest_abs o car) tm 997 in (BETA_CONV THENC ONCE_REWRITE_CONV [GSYM (SPEC v GUARD_def)]) tm end 998 val th = RW [PUSH_IF_LEMMA,GSYM CONJ_ASSOC] (DISCH_ALL th) 999 val th = CONV_RULE (DEPTH_CONV side2guard_conv) (DISCH_ALL th) 1000 val th = CONV_RULE ((RATOR_CONV o RAND_CONV) 1001 (SIMP_CONV bool_ss [GSYM CONJ_ASSOC,NOT_IF])) th 1002 val th = remove_primes th 1003 fun bool_var_assign_conv tm = 1004 if is_conj tm then BINOP_CONV bool_var_assign_conv tm else 1005 if is_cond tm then BINOP_CONV bool_var_assign_conv tm else 1006 if is_var tm andalso type_of tm = ``:bool`` then SPEC tm GUARD_T else 1007 if is_neg tm andalso is_var (cdr tm ) then SPEC (cdr tm) GUARD_F 1008 else ALL_CONV tm 1009 val th = CONV_RULE ((RATOR_CONV o RAND_CONV) bool_var_assign_conv) th 1010 in th end; 1011 1012fun guard_to_num tm = (numSyntax.int_of_term o cdr o car) tm 1013fun assum_to_num tm = 1014 if is_var tm then tagged_var_to_num tm else 1015 if is_neg tm andalso is_var (cdr tm) then tagged_var_to_num (cdr tm) else 1016 if is_cond tm then 100000 else 1017 if can (match_term ``GUARD b x``) tm then guard_to_num tm else 1018 if can (match_term ``~(GUARD b x)``) tm then guard_to_num (cdr tm) else 1019 (hd o map tagged_var_to_num o free_vars o fst o dest_eq) tm 1020 1021fun push_if_inwards th = let 1022 fun drop_until p [] = [] 1023 | drop_until p (x::xs) = if p x then x::xs else drop_until p xs 1024 fun strip_names v = let 1025 val vs = (drop_until (fn x => x = #"@") o explode o fst o dest_var) v 1026 in if vs = [] then (fst o dest_var) v else implode vs end 1027 fun sort_seq tms = let 1028 val xs = all_distinct (map assum_to_num tms) 1029 val xs = sort (fn x => fn y => x <= y) xs 1030 val xs = map (fn x => filter (fn tm => x = assum_to_num tm) tms) xs 1031 fun internal_sort ys = let 1032 val zs = filter (fn tm => can (match_term ``GUARD b x``) tm orelse 1033 can (match_term ``~(GUARD b x)``) tm) ys 1034 val ys = diff ys zs 1035 fun comp tm1 tm2 = let 1036 val (defs,_) = dest_eq tm1 1037 val (_,refs) = dest_eq tm2 1038 in disjoint (map strip_names (free_vars defs)) 1039 (map strip_names (free_vars refs)) end 1040 fun f [] = [] 1041 | f [x] = [x] 1042 | f (x::y::ys) = if comp x y then x :: f (y::ys) else y :: f (x::ys) 1043 in zs @ f ys end 1044 in append_lists (map internal_sort xs) end 1045 fun PUSH_IF_TERM tm = let 1046 val (b,t1,t2) = dest_cond tm 1047 val t1 = PUSH_IF_TERM t1 1048 val t2 = PUSH_IF_TERM t2 1049 val xs1 = list_dest dest_conj t1 1050 val xs2 = list_dest dest_conj t2 1051 val i = guard_to_num b 1052 val ys1 = filter (fn x => assum_to_num x < i) xs1 1053 val ys2 = filter (fn x => assum_to_num x < i) xs2 1054 val _ = if same_set ys1 ys2 then () else hd [] 1055 val zs1 = sort_seq (diff xs1 ys1) 1056 val zs2 = sort_seq (diff xs2 ys2) 1057 val q = mk_cond(b,list_mk_conj zs1,list_mk_conj zs2) 1058 val goal = list_mk_conj(sort_seq ys1 @ [q]) 1059 in goal end handle HOL_ERR _ => 1060 list_mk_conj(sort_seq (list_dest dest_conj tm)) 1061 val th = RW [NOT_IF] (DISCH_ALL th) 1062 val tm = (fst o dest_imp o concl) th 1063 val goal = mk_imp(PUSH_IF_TERM tm,tm) 1064 val simp = SIMP_CONV pure_ss [AC CONJ_ASSOC CONJ_COMM] 1065 val lemma = auto_prove "push_if_inwards" (goal, 1066 REWRITE_TAC [PUSH_IF_LEMMA] 1067 THEN CONV_TAC (RAND_CONV simp THENC (RATOR_CONV o RAND_CONV) simp) 1068 THEN REWRITE_TAC []) 1069 val th = DISCH_ALL (MP th (UNDISCH lemma)) 1070 val th = 1071 CONV_RULE ((RATOR_CONV o RAND_CONV) (SIMP_CONV bool_ss [GUARD_EQ_ZERO])) th 1072 in th end; 1073 1074fun list_dest_exists tm ys = let 1075 val (v,y) = dest_exists tm 1076 in list_dest_exists y (v::ys) end handle e => (rev ys, tm) 1077 1078(* val tm = ``?x. (x = y + 5) /\ x < z /\ t < x`` *) 1079(* val tm = ``?z. (z = x + 5)`` *) 1080 1081fun INST_EXISTS_CONV tm = let 1082 val (v,rest) = dest_exists tm 1083 val (x,rest) = dest_conj rest 1084 val (x,y) = dest_eq x 1085 val th = ISPECL [mk_abs(v,rest),y] UNWIND_THM2 1086 val th = CONV_RULE (RAND_CONV BETA_CONV) th 1087 val th = CONV_RULE ((RATOR_CONV o RAND_CONV o RAND_CONV) 1088 (ALPHA_CONV v THENC ABS_CONV (RAND_CONV BETA_CONV))) th 1089 in if x = v then th else NO_CONV tm end handle HOL_ERR _ => let 1090 val (v,rest) = dest_exists tm 1091 val (x,y) = dest_eq rest 1092 val th = GEN_ALL (SIMP_CONV std_ss [] ``?x:'a. x = a``) 1093 val th = ISPEC y th 1094 val th = CONV_RULE ((RATOR_CONV o RAND_CONV o RAND_CONV) 1095 (ALPHA_CONV v)) th 1096 in if x = v then th else NO_CONV tm end 1097 1098(* val tm = ``!x. foo (FST x, SND (SND x)) = FST (SND x)`` *) 1099 1100val EXPAND_FORALL_CONV = let 1101 fun EXPAND_FORALL_ONCE_CONV tm = 1102 ((QUANT_CONV (UNBETA_CONV (fst (dest_forall tm))) THENC 1103 ONCE_REWRITE_CONV [FORALL_PROD] THENC 1104 (QUANT_CONV o QUANT_CONV) BETA_CONV)) tm 1105 handle HOL_ERR _ => ALL_CONV tm; 1106 in (REPEATC (DEPTH_CONV EXPAND_FORALL_ONCE_CONV)) end 1107 1108(* val tm = ``?z:num. y + x + 5 < 7`` *) 1109 1110fun PUSH_EXISTS_CONST_CONV tm = let 1111 val PUSH_EXISTS_CONST_LEMMA = auto_prove "PUSH_EXISTS_CONST_CONV" 1112 (``!p. (?x:'a. p) = p:bool``, 1113 REPEAT STRIP_TAC THEN EQ_TAC THEN REPEAT STRIP_TAC 1114 THEN EXISTS_TAC (genvar(``:'a``)) THEN ASM_SIMP_TAC std_ss []); 1115 val (v,n) = dest_exists tm 1116 val _ = if mem v (free_vars n) then hd [] else 1 1117 val th = SPEC n (INST_TYPE [``:'a``|->type_of v] PUSH_EXISTS_CONST_LEMMA) 1118 val th = CONV_RULE ((RATOR_CONV o RAND_CONV o RAND_CONV) (ALPHA_CONV v)) th 1119 in th end handle e => NO_CONV tm handle e => NO_CONV tm; 1120 1121(* val tm = ``?x. let (y,z,q) = foo t in y + x + z + 5 = 8 - q`` *) 1122 1123fun PUSH_EXISTS_LET_CONV tm = let 1124 val (v,n) = dest_exists tm 1125 val (x,rest) = pairSyntax.dest_anylet n 1126 val tm2 = pairSyntax.mk_anylet(x,mk_exists(v,rest)) 1127 val goal = mk_eq(tm,tm2) 1128 val c = (RATOR_CONV o RATOR_CONV) (REWRITE_CONV [LET_DEF]) 1129 val thi = auto_prove "PUSH_EXISTS_LET_CONV" (goal, 1130 SPEC_TAC (snd (hd x),genvar(type_of (snd (hd x)))) 1131 THEN CONV_TAC EXPAND_FORALL_CONV THEN REPEAT STRIP_TAC 1132 THEN CONV_TAC ((RAND_CONV) c) 1133 THEN CONV_TAC ((RATOR_CONV o RAND_CONV o QUANT_CONV) c) 1134 THEN NTAC ((length o dest_tuple o fst o hd) x + 1) 1135 (CONV_TAC (ONCE_DEPTH_CONV BETA_CONV) 1136 THEN CONV_TAC (ONCE_DEPTH_CONV BETA_CONV) 1137 THEN REWRITE_TAC [UNCURRY_DEF])) 1138 in thi end handle e => NO_CONV tm 1139 handle e => NO_CONV tm; 1140 1141(* val tm = ``?x y z. if (q = 4) then (x + 1 = 6) else (y - 8 = z)`` *) 1142 1143fun PUSH_EXISTS_COND_CONV tm = let 1144 val (vs,n) = list_dest_exists tm [] 1145 val _ = if vs = [] then hd [] else () 1146 val (b,x1,x2) = dest_cond n 1147 val tm2 = mk_cond(b,list_mk_exists(vs,x1),list_mk_exists(vs,x2)) 1148 val thi = auto_prove "PUSH_EXISTS_COND_CONV" 1149 (mk_eq(tm,tm2),Cases_on [ANTIQUOTE b] THEN ASM_REWRITE_TAC []) 1150 in thi end handle e => NO_CONV tm handle e => NO_CONV tm; 1151 1152(* val tm = ``?x y z. (q = 4) /\ (x + 1 = 6)`` *) 1153 1154fun PUSH_EXISTS_CONJ_CONV tm = let 1155 val (vs,n) = list_dest_exists tm [] 1156 val xs = (list_dest dest_conj n) 1157 val _ = if disjoint (free_vars (hd xs)) vs then () else hd [] 1158 val tm2 = mk_conj(hd xs,list_mk_exists(vs,list_mk_conj(tl xs))) 1159 fun PULL_EXISTS_CONV tm = let 1160 val (x,y) = dest_conj tm 1161 val (v,y) = dest_exists y 1162 val th = ISPEC (mk_abs(v,y)) (SPEC x (GSYM RIGHT_EXISTS_AND_THM)) 1163 val th = CONV_RULE (RAND_CONV ( 1164 RAND_CONV (ALPHA_CONV v) THENC 1165 QUANT_CONV (RAND_CONV BETA_CONV)) THENC 1166 (RATOR_CONV o RAND_CONV) ( 1167 RAND_CONV (RAND_CONV (ALPHA_CONV v) THENC 1168 QUANT_CONV BETA_CONV))) th 1169 in th end handle HOL_ERR _ => NO_CONV tm 1170 val thi = GSYM (REPEATC (ONCE_DEPTH_CONV PULL_EXISTS_CONV) tm2) 1171 in thi end handle e => NO_CONV tm handle e => NO_CONV tm; 1172 1173(* val tm = ``?x y z. 5 = 6 + tg`` *) 1174 1175fun PUSH_EXISTS_EMPTY_CONV tm = let 1176 fun DELETE_EXISTS_CONV tm = let 1177 val (v,rest) = dest_exists tm 1178 val _ = if mem v (free_vars rest) then hd [] else () 1179 val w = genvar(``:bool``) 1180 val th = INST_TYPE [``:'a``|->type_of v] (SPEC w boolTheory.EXISTS_SIMP) 1181 val th = CONV_RULE ((RATOR_CONV o RAND_CONV o RAND_CONV) (ALPHA_CONV v)) th 1182 in INST [w |-> rest] th end handle e => NO_CONV tm 1183 val th = DEPTH_CONV DELETE_EXISTS_CONV tm 1184 in if (is_exists o cdr o concl) th then NO_CONV tm else th end 1185 1186fun DEPTH_EXISTS_CONV c tm = 1187 if is_exists tm then (c THENC DEPTH_EXISTS_CONV c) tm else 1188 if can (match_term ``GUARD n x``) tm then ALL_CONV tm else 1189 if is_comb tm then (RATOR_CONV (DEPTH_EXISTS_CONV c) THENC 1190 RAND_CONV (DEPTH_EXISTS_CONV c)) tm else 1191 if is_abs tm then ABS_CONV (DEPTH_EXISTS_CONV c) tm else ALL_CONV tm; 1192 1193fun EXPAND_BASIC_LET_CONV tm = let 1194 val (xs,x) = pairSyntax.dest_anylet tm 1195 val (lhs,rhs) = hd xs 1196 val ys = dest_tuple lhs 1197 val zs = dest_tuple rhs 1198 val _ = if length zs = length ys then () else hd [] 1199 fun every p [] = true 1200 | every p (x::xs) = if p x then every p xs else hd [] 1201 val _ = every (fn x => every is_var (list_dest dest_conj x)) zs 1202 in (((RATOR_CONV o RATOR_CONV) (REWRITE_CONV [LET_DEF])) 1203 THENC DEPTH_CONV PairRules.PBETA_CONV) tm end 1204 handle e => NO_CONV tm; 1205 1206fun STRIP_FORALL_TAC (hs,tm) = 1207 if is_forall tm then STRIP_TAC (hs,tm) else NO_TAC (hs,tm) 1208 1209fun SPEC_AND_CASES_TAC x = 1210 SPEC_TAC (x,genvar(type_of x)) THEN Cases THEN REWRITE_TAC [] 1211 1212fun GENSPEC_TAC [] = SIMP_TAC pure_ss [FORALL_PROD] 1213 | GENSPEC_TAC (x::xs) = SPEC_TAC (x,genvar(type_of x)) THEN GENSPEC_TAC xs; 1214 1215val EXPAND_BASIC_LET_TAC = 1216 CONV_TAC (DEPTH_CONV EXPAND_BASIC_LET_CONV) 1217 THEN REPEAT STRIP_FORALL_TAC 1218 1219fun AUTO_DECONSTRUCT_TAC finder (hs,goal) = let 1220 val tm = finder goal 1221 in if is_cond tm then let 1222 val (b,_,_) = dest_cond tm 1223 in SPEC_AND_CASES_TAC b (hs,goal) end 1224 else if is_let tm then let 1225 val (v,c) = (hd o fst o pairSyntax.dest_anylet) tm 1226 val c = if not (type_of c = ``:bool``) then c else 1227 (find_term (can (match_term ``GUARD x b``)) c handle e => c) 1228 val cs = dest_tuple c 1229 in (GENSPEC_TAC cs THEN EXPAND_BASIC_LET_TAC) (hs,goal) end 1230 else (REWRITE_TAC [] THEN NO_TAC) (hs,goal) end 1231 1232(* val v = ``v:num`` 1233 val c = ``c:num`` 1234 val tm = 1235 ``?x y v z. (x = 5) /\ (y = x + 6) /\ (v = c) /\ (z = v) /\ (n = v:num)`` 1236*) 1237 1238fun FAST_EXISTS_INST_CONV v c tm = let 1239 val (x,y) = dest_exists tm 1240 in if not (x = v) then QUANT_CONV (FAST_EXISTS_INST_CONV v c) tm else let 1241 val imp = SPEC (mk_abs(v,y)) (ISPEC c EXISTS_EQ_LEMMA) 1242 val thi = MP (CONV_RULE ((RATOR_CONV o RAND_CONV) (SIMP_CONV bool_ss [])) imp) TRUTH 1243 val thi = CONV_RULE (RAND_CONV BETA_CONV THENC 1244 (RATOR_CONV o RAND_CONV o RAND_CONV) (ALPHA_CONV v) THENC 1245 (RATOR_CONV o RAND_CONV o QUANT_CONV) BETA_CONV) thi 1246 in thi end end; 1247 1248fun SUBST_EXISTS_CONV_AUX [] cs = ALL_CONV 1249 | SUBST_EXISTS_CONV_AUX vs [] = ALL_CONV 1250 | SUBST_EXISTS_CONV_AUX (v::vs) (c::cs) = 1251 FAST_EXISTS_INST_CONV v c THENC SUBST_EXISTS_CONV_AUX vs cs; 1252 1253fun SUBST_EXISTS_CONV vs cs = 1254 PURE_REWRITE_CONV [PAIR_EQ,GSYM CONJ_ASSOC] 1255 THENC SUBST_EXISTS_CONV_AUX vs cs 1256 THENC REWRITE_CONV []; 1257 1258(* 1259fun PRINT_GOAL_TAC s (hs,goal) = let 1260 val _ = print "\n\n" 1261 val _ = print s 1262 val _ = print ":\n\n" 1263 val _ = print_term goal 1264 val _ = print "\n\n" 1265 in ALL_TAC (hs,goal) end; 1266*) 1267 1268fun GUIDED_INST_EXISTS_TAC finder1 cc2 (hs,goal) = let 1269 val tm = finder1 goal 1270 val (xs,x) = pairSyntax.dest_anylet tm 1271 val (lhs,rhs) = hd xs 1272 val ys = dest_tuple lhs 1273 val zs = dest_tuple rhs 1274 val _ = if length zs = length ys then () else hd [] 1275 val cond_var = mk_var("cond",``:bool``) 1276 in (if ys = [cond_var] then ALL_TAC (hs,goal) 1277 else CONV_TAC (cc2 (SUBST_EXISTS_CONV ys zs)) (hs,goal)) end 1278 handle e => let 1279 val _ = print "\n\nGUIDED_INST_EXISTS_TAC should not fail.\n\nGoal:\n\n" 1280 val _ = print_term goal 1281 val _ = print "\n\n" 1282 in raise e end; 1283 1284fun AUTO_DECONSTRUCT_EXISTS_TAC finder1 (cc1,cc2) (hs,goal) = let 1285 val tm = finder1 goal 1286 in if is_cond tm then let 1287 val (b,_,_) = dest_cond tm 1288 in SPEC_AND_CASES_TAC b (hs,goal) end 1289 else if is_let tm then let 1290 val cond_var = mk_var("cond",``:bool``) 1291 val (v,c) = (hd o fst o pairSyntax.dest_anylet) tm 1292 val c = if not (v = cond_var) then c 1293 else (find_term (can (match_term ``GUARD x b``)) c 1294 handle e => ``GUARD 1000 F`` (* unlikely term *)) 1295 val cs = dest_tuple c 1296 in (GENSPEC_TAC cs 1297 THEN REPEAT STRIP_TAC 1298 THEN REWRITE_TAC [] 1299 THEN GUIDED_INST_EXISTS_TAC finder1 cc2 1300 THEN CONV_TAC (cc1 EXPAND_BASIC_LET_CONV) 1301 THEN REWRITE_TAC []) (hs,goal) end 1302 else (REWRITE_TAC [] THEN NO_TAC) (hs,goal) end; 1303 1304fun one_step_let_intro th = let 1305 val tm = fst (dest_imp (concl th)) 1306 val g = last (list_dest boolSyntax.dest_exists tm) 1307 fun let_term tm = let 1308 val (g,x,y) = dest_cond tm 1309 in FUN_IF (g,let_term x,let_term y) end handle e => let 1310 val (x,y) = dest_conj tm 1311 in if can (match_term ``GUARD n y``) x 1312 then FUN_COND (x,let_term y) 1313 else let 1314 val (x1,x2) = dest_eq x 1315 val xs1 = dest_tuple x1 1316 in if is_new_var x1 1317 then FUN_VAL (mk_conj(tm,mk_var("cond",``:bool``))) 1318 else FUN_LET (x1,x2,let_term y) 1319 end end 1320 val let_tm = 1321 subst [mk_var("cond",``:bool``)|->``T:bool``] (ftree2tm (let_term g)) 1322 val goal = mk_eq(tm,let_tm) 1323(* 1324set_goal([],goal) 1325*) 1326 val thi = RW [GSYM CONJ_ASSOC] (auto_prove "one_step_let_intro" (goal, 1327 REWRITE_TAC [] 1328 THEN REPEAT (AUTO_DECONSTRUCT_EXISTS_TAC cdr 1329 (RAND_CONV, RATOR_CONV o RAND_CONV)) 1330 THEN SIMP_TAC pure_ss [AC CONJ_ASSOC CONJ_COMM] THEN REWRITE_TAC [] 1331 THEN EQ_TAC THEN REPEAT STRIP_TAC THEN ASM_REWRITE_TAC [])) 1332 val th = RW1 [thi] th 1333 in th end; 1334 1335fun remove_constant_new_assigment avoid_vars th = let 1336 val vs = filter is_new_var (free_vars (concl th)) 1337 fun is_real_assign tm = let 1338 val (x,y) = dest_eq tm 1339 in not (dest_new_var x = y) end handle HOL_ERR _ => false 1340 val ws = map (fst o dest_eq) (find_terms is_real_assign (concl th)) 1341 val ws = diff vs ws 1342 val th1 = RW [] (INST (map (fn x => x |-> dest_new_var x) ws) th) 1343 val ts = (free_vars o fst o dest_imp o concl) th1 1344 fun mk_new_var v = let val (n,t) = dest_var v in mk_var("new@"^n,t) end 1345 val ws = diff (map dest_new_var ws) (ts @ avoid_vars) 1346 val th = RW [] (INST (map (fn x => mk_new_var x |-> x) ws) th) 1347 in th end; 1348 1349fun introduce_lets th = let 1350 val th = init_clean th 1351 val th = push_if_inwards th 1352 val (lhs,rhs) = (dest_imp o concl) th 1353 val vs = diff (free_vars lhs) (free_vars rhs) 1354 val vs = filter (fn v => not (read_tag v = "new")) vs 1355 val th = CONV_RULE ((RATOR_CONV o RAND_CONV) 1356 (ONCE_REWRITE_CONV [GSYM CONTAINER_def])) th 1357 val th = SIMP_RULE bool_ss [LEFT_FORALL_IMP_THM] (GENL vs th) 1358 val th = RW1 [CONTAINER_def] th 1359 val th = one_step_let_intro th 1360 in th end; 1361 1362fun raw_tm2ftree tm = let 1363 val (x,y) = dest_conj tm 1364 val _ = if can (match_term ``GUARD b x``) x then () else fail() 1365 in FUN_COND (x,raw_tm2ftree y) end handle e => let 1366 val (b,x,y) = dest_cond tm 1367 in FUN_IF (b,raw_tm2ftree x,raw_tm2ftree y) end handle e => let 1368 val (x,y) = pairSyntax.dest_anylet tm 1369 val z = raw_tm2ftree y 1370 fun g((x,y),z) = FUN_LET (x,y,z) 1371 in foldr g z x end handle e => FUN_VAL tm; 1372 1373(* sorts in alphabetical order except for r1,r2,r3 which will come first *) 1374val var_sorter = let 1375 fun dest_reg_var s = let 1376 val xs = explode s 1377 in if hd xs = #"r" then string_to_int (implode (tl xs)) else fail() end 1378 val is_reg_var = can dest_reg_var 1379 fun name_of_var tm = let 1380 val s = fst (dest_var tm) 1381 in if s = "eax" then "r0" else 1382 if s = "ecx" then "r1" else 1383 if s = "edx" then "r2" else 1384 if s = "ebx" then "r3" else 1385 if s = "esp" then "r4" else 1386 if s = "ebp" then "r5" else 1387 if s = "esi" then "r6" else 1388 if s = "edi" then "r7" else s end 1389 fun cmp tm1 tm2 = let 1390 val s1 = name_of_var tm1 1391 val s2 = name_of_var tm2 1392 in if is_reg_var s1 = is_reg_var s2 1393 then (dest_reg_var s1 < dest_reg_var s2 handle e => s1 < s2) 1394 else is_reg_var s1 end 1395 in sort cmp end 1396 1397fun leaves (FUN_VAL tm) f = FUN_VAL (f tm) 1398 | leaves (FUN_COND (c,t)) f = FUN_COND (c, leaves t f) 1399 | leaves (FUN_IF (a,b,c)) f = FUN_IF (a, leaves b f, leaves c f) 1400 | leaves (FUN_LET (v,y,t)) f = FUN_LET (v, y, leaves t f) 1401 1402fun erase_conds (FUN_VAL tm) = FUN_VAL tm 1403 | erase_conds (FUN_COND (c,t)) = erase_conds t 1404 | erase_conds (FUN_IF (a,b,c)) = FUN_IF (a,erase_conds b,erase_conds c) 1405 | erase_conds (FUN_LET (x,y,t)) = FUN_LET (x,y,erase_conds t) 1406 1407val REMOVE_TAGS_CONV = let 1408 val alpha_lemma = prove(``!b:bool. (b = T) ==> b``,Cases THEN REWRITE_TAC []); 1409 fun REMOVE_TAG_CONV tm = let 1410 val (v,x) = dest_abs tm 1411 val xs = free_vars x 1412 fun d [] = fail() 1413 | d (x::xs) = if x = #"@" then implode xs else d xs 1414 fun strip_tag v = mk_var((d o explode o fst o dest_var) v, type_of v) 1415 fun add_prime v = mk_var(fst (dest_var v) ^ "'", type_of v) 1416 fun is_ok v = not (mem v xs) 1417 fun UNTIL g f x = if g x then x else UNTIL g f (f x) 1418 val w = UNTIL is_ok add_prime (strip_tag v) 1419 val thi = 1420 SIMP_CONV std_ss [FUN_EQ_THM] (mk_eq(tm,mk_abs(w,subst [v|->w] x))) 1421 in MATCH_MP alpha_lemma thi end handle e => NO_CONV tm 1422 in (DEPTH_CONV REMOVE_TAG_CONV THENC REWRITE_CONV [GUARD_def]) end; 1423 1424fun simplify_and_define name x_in rhs = let (* *) 1425 val ty = mk_type("fun",[type_of x_in, type_of rhs]) 1426 val rw = REMOVE_TAGS_CONV rhs handle HOL_ERR _ => REFL rhs 1427 val tm = mk_eq(mk_comb(mk_var(name,ty),x_in),cdr (concl rw)) 1428 val def = SPEC_ALL (new_definition(name ^ "_def", tm)) handle e => 1429 (print ("\n\nERROR: Cannot define " ^ name ^ "_def as,\n\n"); 1430 print_term tm; print "\n\n"; raise e) 1431 in CONV_RULE (RAND_CONV (fn tm => GSYM rw)) def end; 1432 1433fun pull_T (FUN_VAL tm) = FUN_VAL tm 1434 | pull_T (FUN_COND tm) = FUN_COND tm 1435 | pull_T (FUN_IF (tm,x,y)) = let 1436 val x' = pull_T x 1437 val y' = pull_T y 1438 in if ((x' = FUN_VAL ``T:bool``) andalso (y' = FUN_VAL ``T:bool``)) orelse 1439 (x' = y') 1440 then x' else FUN_IF (tm,x',y') end 1441 | pull_T (FUN_LET (tm,tn,x)) = let 1442 val x' = pull_T x 1443 val vs = free_vars (ftree2tm x') 1444 val ws = free_vars tm 1445 in if filter (fn v => mem v ws) vs = [] then x' else FUN_LET (tm,tn,x') 1446 end 1447 1448fun simplify_pre pre th = let 1449 val ft = pull_T (tm2ftree ((cdr o concl o SPEC_ALL) pre)) 1450 val goal = mk_comb((car o concl o SPEC_ALL) pre, ftree2tm ft) 1451 in if not (ft = FUN_VAL ``T``) then (th,pre) else let 1452 val new_pre = (auto_prove "simplify_pre" (goal, 1453 REWRITE_TAC [] 1454 THEN ONCE_REWRITE_TAC [pre] 1455 THEN REPEAT (AUTO_DECONSTRUCT_TAC I))) 1456 val th = RW [new_pre,SEP_CLAUSES] th 1457 in (th,new_pre) end end 1458 1459fun introduce_post_let th = let 1460 val (x,y) = (dest_comb o cdr o concl) th 1461 val (x,z) = pairSyntax.dest_pabs x 1462 val tm = pairSyntax.mk_anylet([(x,y)],z) 1463 val th1 = GSYM (SIMP_CONV std_ss [LET_DEF] tm) 1464 in CONV_RULE (RAND_CONV (ONCE_REWRITE_CONV [th1])) 1465 (SIMP_RULE std_ss [] th) end handle e => th; 1466 1467fun REMOVE_VARS_FROM_THM vs th = let 1468 fun REMOVE_FROM_LHS (v,th) = let 1469 val th = SIMP_RULE pure_ss [LEFT_FORALL_IMP_THM] (GEN v th) 1470 val c = DEPTH_EXISTS_CONV (PUSH_EXISTS_COND_CONV ORELSEC 1471 PUSH_EXISTS_LET_CONV ORELSEC 1472 PUSH_EXISTS_CONJ_CONV ORELSEC 1473 INST_EXISTS_CONV ORELSEC 1474 PUSH_EXISTS_CONST_CONV) 1475 val th = CONV_RULE ((RATOR_CONV o RAND_CONV) c) th 1476 in th end 1477 in foldr REMOVE_FROM_LHS th vs end 1478 1479fun HIDE_POST_VARS vs th = let 1480 val th = CONV_RULE ((RATOR_CONV o RAND_CONV) 1481 (ONCE_REWRITE_CONV [GSYM CONTAINER_def])) th 1482 val th = foldr (uncurry SEP_EXISTS_POST_RULE) (UNDISCH_ALL th) vs 1483 val th = SEP_EXISTS_ELIM_RULE th 1484 val th = RW [CONTAINER_def] (DISCH_ALL th) 1485 val th = REMOVE_VARS_FROM_THM vs th 1486 in th end; 1487 1488fun HIDE_PRE_VARS vs th1 = let 1489 val th = CONV_RULE ((RATOR_CONV o RAND_CONV) 1490 (ONCE_REWRITE_CONV [GSYM CONTAINER_def])) th1 1491 val th = foldr (uncurry SEP_EXISTS_PRE_RULE) (UNDISCH_ALL th) vs 1492 val th = SEP_EXISTS_ELIM_RULE th 1493 val th = RW [CONTAINER_def] (DISCH_ALL th) 1494 in th end; 1495 1496fun SORT_SEP_CONV tm = let 1497 fun remove_tags tm = 1498 subst (map (fn v => v |-> mk_var(strip_tag v,type_of v)) (free_vars tm)) tm 1499 val xs = list_dest dest_star tm 1500 fun compare tm1 tm2 = let 1501 val s1 = term_to_string (remove_tags (get_sep_domain tm1)) 1502 val s2 = term_to_string (remove_tags (get_sep_domain tm2)) 1503 in if size s2 < size s1 then 1 < 2 else 1504 if size s1 < size s2 then 2 < 1 else 1505 if not (s1 = s2) then s1 < s2 else 1506 term_to_string (remove_tags tm1) < term_to_string (remove_tags tm2) end 1507 val tm2 = list_mk_star (sort compare xs) (type_of tm) 1508 val thi = 1509 auto_prove "SORT_SEP_CONV" (mk_eq(tm,tm2),SIMP_TAC (bool_ss++star_ss) []) 1510 in thi end; 1511 1512fun LET_EXPAND_POS_CONV tm = let 1513 val x = (fst o dest_abs o fst o dest_let) tm 1514 in if not (x = mk_var("pos",``:num``)) then fail () else 1515 ((RATOR_CONV o RATOR_CONV) (ONCE_REWRITE_CONV [LET_DEF]) 1516 THENC RATOR_CONV BETA_CONV THENC BETA_CONV THENC BETA_CONV) tm end 1517 handle HOL_ERR _ => NO_CONV tm; 1518 1519fun DEST_NEW_VAR_CONV tm = 1520 ALPHA_CONV (dest_new_var (fst (dest_abs tm))) tm 1521 handle HOL_ERR _ => NO_CONV tm; 1522 1523fun SEP_EXISTS_CONV c tm = 1524 if can dest_sep_exists tm 1525 then RAND_CONV (ABS_CONV (SEP_EXISTS_CONV c)) tm else ALL_CONV tm; 1526 (* is this right? shouldn't it be: c tm *) 1527 1528fun SEP_DISJ_CONV c tm = 1529 if can dest_sep_disj tm 1530 then ((RATOR_CONV o RAND_CONV) c) tm else c tm; 1531 1532val GEN_TUPLE_LEMMA = GSYM (CONV_RULE ((RATOR_CONV o RAND_CONV o RAND_CONV) 1533 (ALPHA_CONV (mk_var("_",``:'a # 'b``)))) FORALL_PROD) 1534fun GEN_TUPLE tm th = 1535 if not (pairSyntax.is_pair tm) then GEN tm th else let 1536 val (w,tm2) = pairSyntax.dest_pair tm 1537 val th = GEN_TUPLE tm2 th 1538 val v = fst (dest_forall (concl th)) 1539 val th = CONV_RULE (UNBETA_CONV (pairSyntax.mk_pair(w,v))) (SPEC v th) 1540 val x = genvar(type_of tm) 1541 val th = 1542 GEN x (CONV_RULE BETA_CONV 1543 (SPEC x (PURE_REWRITE_RULE [GEN_TUPLE_LEMMA] (GEN w (GEN v th))))) 1544 in th end; 1545 1546fun extract_function name th entry exit function_in_out = let 1547 val _ = echo 1 " extracting function," 1548 val output = (filter (not o is_new_var) o free_vars o cdr o concl) th 1549 fun drop_until p [] = [] 1550 | drop_until p (x::xs) = if p x then x::xs else drop_until p xs 1551 fun strip_names v = let 1552 val vs = (tl o drop_until (fn x => x = #"@") o explode o fst o dest_var) v 1553 in if vs = [] then (fst o dest_var) v else implode vs end 1554 handle e => (fst o dest_var) v 1555 fun new_abbrev (v,th) = let 1556 val th = RW [GSYM SPEC_MOVE_COND] (DISCH_ALL th) 1557 val n = "new@" ^ strip_names v 1558 val th = raw_abbreviate2 (n,v,v) th 1559 val th = RW [SPEC_MOVE_COND,AND_IMP_INTRO] (DISCH_ALL th) 1560 val th = RW [PUSH_IF_LEMMA] th 1561 in th end 1562 val th = foldr new_abbrev th output 1563 val th = introduce_lets th 1564 val avoid_vars = 1565 case function_in_out of NONE => [] | SOME (p,q) => free_vars q 1566 val th = remove_constant_new_assigment avoid_vars th 1567 val pc = get_pc() 1568 val pc_type = (hd o snd o dest_type o type_of) pc 1569 val th = INST [mk_var("new@p",pc_type) |-> mk_var("set@p",pc_type)] th 1570 val t = tm2ftree ((cdr o car o concl o RW [WORD_ADD_0]) th) 1571 (* extract: step function and input, output tuples *) 1572 fun gen_pc n = if n = 0 then mk_var("p",pc_type) else 1573 (ASSUME (mk_eq(mk_var("_",pc_type),mk_var("p",pc_type)))) 1574 |> (!decompiler_set_pc) n |> concl |> cdr 1575 handle HOL_ERR _ => subst [mk_var("n",``:num``) |-> numSyntax.term_of_int n] 1576 (inst [``:'a``|->(hd o tl o snd o dest_type) pc_type] 1577 ``(p:'a word) + n2w n``) 1578 val exit_tm = gen_pc (hd exit) 1579 val entry_tm = (snd o dest_eq o find_term (fn tm => let 1580 val (x,y) = dest_eq tm 1581 in fst (dest_var x) = "set@p" andalso not (y = exit_tm) end 1582 handle HOL_ERR _ => false) o concl) th 1583 handle HOL_ERR _ => gen_pc (hd entry) 1584 val final_node = mk_eq(mk_var("set@p",pc_type),exit_tm) 1585 fun is_terminal_node tm = can (find_term (fn x => x = final_node)) tm 1586 val output = (filter is_new_var o free_vars o cdr o cdr o concl) th 1587 fun strip_tag v = 1588 mk_var((implode o drop 4 o explode o fst o dest_var) v, type_of v) 1589 val output = var_sorter (map strip_tag output) 1590 fun rm_pc tm = let 1591 val xs = find_terms (fn x => fst (dest_eq x) = mk_var("set@p",pc_type) 1592 handle HOL_ERR _ => false) tm 1593 in subst (map (fn x => x |-> T) xs) tm end 1594 val iii = (list_mk_pair o var_sorter o filter (not o is_new_var) o 1595 free_vars o rm_pc o ftree2tm o leaves t) 1596 (fn x => if is_terminal_node x then x else ``T:bool``) 1597 val input = (var_sorter o filter (not o is_new_var) o filter (fn v => not (v = mk_var("cond",``:bool``))) o 1598 free_vars o rm_pc o ftree2tm o leaves t) 1599 (fn x => if is_terminal_node x then x else mk_eq(iii,iii)) 1600 val input = if input = [] then [mk_var("()",``:unit``)] else input 1601 fun set_input_output NONE = (input,output) 1602 | set_input_output (SOME (ix,ox)) = (dest_tuple ix, dest_tuple ox) 1603 val (input,output) = set_input_output function_in_out 1604 val pos_subst = mk_var("pos",``:num``) |-> mk_var("s10000@pos",``:num``) 1605 val new_pos_subst = 1606 mk_var("s10000@pos",``:num``) |-> mk_var("new@pos",``:num``) 1607 fun new_into_subst tm = let 1608 val vs = list_dest dest_conj tm 1609 val vs = filter is_eq vs 1610 in subst 1611 (pos_subst :: 1612 map (fn x => let val (x,y) = dest_eq x in (strip_tag x) |-> y end) vs) 1613 end 1614 val x_in = list_mk_pair input 1615 val x_out = list_mk_pair output 1616 fun add_new_tag v = mk_var("new@" ^ fst (dest_var v), type_of v) 1617 val new_output = list_mk_pair (map add_new_tag output) 1618 val new_input = list_mk_pair (map add_new_tag input) 1619 val cond_var = mk_var("cond",``:bool``) 1620 fun mk_exit tm = pairSyntax.mk_pair(tm,cond_var) 1621 val step_fun = 1622 mk_pabs(x_in,ftree2tm (leaves t (fn x => 1623 if is_terminal_node x 1624 then mk_exit(sumSyntax.mk_inr 1625 (new_into_subst x x_out,type_of x_in)) 1626 else mk_exit(sumSyntax.mk_inl 1627 (new_into_subst x x_in,type_of x_out))))) 1628 val step_fun = 1629 (snd o dest_eq o concl o QCONV (REWRITE_CONV [GSYM CONJ_ASSOC])) 1630 (subst [cond_var |-> T] step_fun) 1631 (* define functions *) 1632 val func_name = name 1633 val tm_option = NONE 1634 val (main_thm,main_def,pre_thm,pre_def) = 1635 tailrecLib.tailrec_define_from_step func_name step_fun tm_option 1636 val finalise = 1637 CONV_RULE (REMOVE_TAGS_CONV THENC DEPTH_CONV (LET_EXPAND_POS_CONV)) 1638 val main_thm = finalise main_thm 1639 val pre_thm = finalise pre_thm 1640 (* define temporary abbreviation *) 1641 val silly_string = Theory.temp_binding "(( step ))" 1642 val step_def = 1643 new_definition 1644 (silly_string,mk_eq(mk_var(silly_string,type_of step_fun),step_fun)) 1645 val main_def = RW [GSYM step_def] main_def 1646 val pre_def = RW [GSYM step_def] pre_def 1647 val step_const = (fst o dest_eq o concl) step_def 1648(* 1649 (* try automatically proving pre = T, i.e. termination *) 1650 val pre_thm = let 1651 val tt = (fst o dest_eq o concl o SPEC_ALL o RW1 [FUN_EQ_THM]) pre_def 1652 val goal = mk_forall(cdr tt,mk_eq(tt,``T:bool``)) 1653 val dummy_name = "no_name" 1654 val c = (repeat car o fst o dest_eq o concl o SPEC_ALL) main_thm 1655 val v = mk_var(dummy_name,type_of c) 1656 val fake_eq = subst [c|->v] ((concl o SPEC_ALL) main_thm) 1657 val defn = Hol_defn dummy_name [ANTIQUOTE fake_eq] 1658 val gs = TotalDefn.guessR defn 1659 fun case_tac x = 1660 TotalDefn.WF_REL_TAC [ANTIQUOTE x] 1661 THEN SRW_TAC [] [] THEN SIMP_TAC std_ss [GSYM word_sub_def] 1662 THEN REPEAT (POP_ASSUM MP_TAC) 1663 THEN SIMP_TAC std_ss (!termination_simps) THEN NO_TAC 1664 val AUX_TAC = FIRST (map case_tac gs) 1665 (* set_goal([],goal) *) 1666 val tac = 1667 PURE_REWRITE_TAC [pre_def,tailrecTheory.SHORT_TAILREC_PRE_def] 1668 THEN MATCH_MP_TAC tailrecTheory.TAILREC_PRE_IMP 1669 THEN Tactical.REVERSE STRIP_TAC 1670 THEN1 (SIMP_TAC std_ss [pairTheory.FORALL_PROD] 1671 THEN SRW_TAC [] [step_def,LET_DEF]) 1672 THEN SIMP_TAC std_ss [step_def,LET_DEF,pairTheory.FORALL_PROD,GUARD_def] 1673 THEN AUX_TAC 1674 val pre_thm = (snd o tac) ([],goal) [] 1675 val _ = echo 1 " (termination automatically proved)," 1676 in pre_thm end handle HOL_ERR _ => pre_thm 1677*) 1678 (* prove lemmas for final proof *) 1679 val _ = echo 1 " proving certificate," 1680 val (th1,th2) = (th,th) 1681 val finder = cdr o el 2 o list_dest dest_conj o fst o dest_imp 1682 val tac2 = SIMP_TAC std_ss [step_def] 1683 THEN REPEAT (AUTO_DECONSTRUCT_TAC finder) 1684 THEN SIMP_TAC std_ss [sumTheory.OUTL,sumTheory.OUTR, 1685 sumTheory.ISR,sumTheory.ISL] 1686 val thi = ISPEC step_const SPEC_SHORT_TAILREC 1687 val thi = RW [GSYM main_def, GSYM pre_def] thi 1688 val lemma1 = let 1689 val th1 = INST [mk_var("set@p",pc_type) |-> exit_tm] th1 1690 val th1 = DISCH_ALL_AS_SINGLE_IMP (RW [] th1) 1691 val post = (free_vars o cdr o snd o dest_imp o concl) th1 1692 val top = (free_vars o fst o dest_imp o concl) th1 1693 val new_top = filter is_new_var top 1694 val vs = diff new_top (dest_tuple new_output @ output) 1695 val th1 = remove_primes (HIDE_POST_VARS vs th1) 1696 val pre = (free_vars o cdr o car o car o snd o dest_imp o concl) th1 1697 val ws = diff pre (mk_var("p",pc_type)::input) 1698 val tm = (fst o dest_imp o concl o DISCH_ALL) th1 1699 val ts = (list_dest dest_forall o snd o dest_conj o fst o dest_imp o 1700 concl o SPEC_ALL) thi 1701 val goal = (fst o dest_imp o last) ts 1702 val goal = subst [el 1 ts |-> x_in, el 2 ts |-> new_output] goal 1703 val goal = mk_imp(goal,tm) 1704 val lemma = UNDISCH (auto_prove "lemma1" (goal,tac2)) 1705 val lemma1 = DISCH_ALL (MP th1 lemma) 1706 val (_,_,_,q) = dest_spec (concl (UNDISCH th1)) 1707 val ws = diff ws (free_vars q) 1708 val lemma1 = HIDE_PRE_VARS ws lemma1 1709 in RW [GSYM step_def] lemma1 end 1710 handle e => (print "\n\nDecompiler failed to prove 'lemma 1'.\n\n"; raise e) 1711 val lemma2 = let 1712 val e_tm = subst [new_pos_subst] entry_tm 1713 val th2 = INST [mk_var("set@p",pc_type) |-> e_tm] th2 1714 val th2 = RW [WORD_ADD_0] th2 1715 val post = (free_vars o cdr o snd o dest_imp o concl) th1 1716 val top = (free_vars o fst o dest_imp o concl) th1 1717 val new_top = filter is_new_var top 1718 val vs = diff new_top (dest_tuple new_input) 1719 val th2 = remove_primes (HIDE_POST_VARS vs th2) 1720 val pre = (free_vars o cdr o car o car o snd o dest_imp o concl) th2 1721 val vs = diff pre (mk_var("p",pc_type)::input) 1722 val tm = (fst o dest_imp o concl o DISCH_ALL) th2 1723 val ts = (list_dest dest_forall o fst o dest_conj o fst o dest_imp o 1724 concl o SPEC_ALL) thi 1725 val goal = (fst o dest_imp o last) ts 1726 val goal = subst [el 1 ts |-> x_in, el 2 ts |-> new_input] goal 1727 val goal = mk_imp(goal,tm) 1728 val lemma = UNDISCH (auto_prove "lemma2" (goal,tac2)) 1729 val lemma2 = DISCH_ALL (MP th2 lemma) 1730 val (_,_,_,q) = dest_spec (concl (UNDISCH th2)) 1731 val ws = diff vs (free_vars q) 1732 val lemma2 = HIDE_PRE_VARS ws lemma2 1733 in RW [GSYM step_def] lemma2 end 1734 handle e => (print "\n\nDecompiler failed to prove 'lemma 2'.\n\n"; raise e) 1735 val sort_conv = PRE_CONV (SEP_EXISTS_CONV SORT_SEP_CONV) THENC 1736 POST_CONV (SEP_EXISTS_CONV (SEP_DISJ_CONV SORT_SEP_CONV)) 1737 val lemma1 = CONV_RULE (RAND_CONV sort_conv) lemma1 1738 val lemma2 = CONV_RULE (RAND_CONV sort_conv) lemma2 1739 (* simplification for cases of non-recursive functions *) 1740 val simp_lemma = let 1741 val (x,y) = dest_eq (concl (SPEC_ALL main_thm)) 1742 val _ = if can (find_term (fn tm => car x = tm)) y then fail () else () 1743 val goal = mk_eq((fst o dest_imp o concl o 1744 ISPEC (pairSyntax.mk_fst(mk_comb(step_fun,x_in)))) sumTheory.INL,F) 1745 val simp_lemma = auto_prove "simp_lemma" (goal,SIMP_TAC std_ss [] 1746 THEN REPEAT (AUTO_DECONSTRUCT_TAC (cdr o cdr)) 1747 THEN SIMP_TAC std_ss []) 1748 val simp_lemma = Q.SPEC `x` (GEN_TUPLE x_in simp_lemma) 1749 val simp_lemma = PURE_REWRITE_RULE [GSYM step_def] simp_lemma 1750 in GEN_ALL simp_lemma end handle HOL_ERR _ => TRUTH 1751 (* deal with SEP_DISJ in post -- move to pre *) 1752 val lemma1 = DISCH_ALL (MATCH_MP SPEC_PRE_DISJ_INTRO (UNDISCH lemma1)) 1753 handle HOL_ERR _ => lemma1 1754 val lemma2 = DISCH_ALL (MATCH_MP SPEC_PRE_DISJ_INTRO (UNDISCH lemma2)) 1755 handle HOL_ERR _ => lemma2 1756 (* certificate theorem *) 1757 fun remove_new_tags tm = let 1758 val vs = filter is_new_var (free_vars tm) 1759 in subst (map (fn v => v |-> strip_tag v) vs) tm end 1760 val (m,p,c,q) = (dest_spec o concl o UNDISCH_ALL) lemma1 1761 val thi = ISPEC (mk_pabs(x_in,p)) thi 1762 val thi = ISPEC (mk_pabs(x_out,remove_new_tags q)) thi 1763 val thi = ISPEC c thi 1764 val thi = ISPEC m thi 1765 val xi = GSYM (SIMP_CONV std_ss [] (mk_comb(mk_pabs(x_in,p),x_in))) 1766 val xin = GSYM (SIMP_CONV std_ss [] (mk_comb(mk_pabs(x_in,p),new_input))) 1767 val xon = GSYM (SIMP_CONV std_ss [] 1768 (mk_comb(mk_pabs(x_out,remove_new_tags q),new_output))) 1769 fun fix_star rw = 1770 SIMP_CONV (bool_ss++star_ss) [] 1771 THENC ONCE_REWRITE_CONV 1772 [CONV_RULE (RATOR_CONV (SIMP_CONV (bool_ss++star_ss) [])) rw] 1773 val l1 = CONV_RULE (RAND_CONV (PRE_CONV (fix_star xi) THENC 1774 POST_CONV (fix_star xon))) lemma1 1775 val l2 = CONV_RULE (RAND_CONV (PRE_CONV (fix_star xi) THENC 1776 POST_CONV (fix_star xin))) lemma2 1777 val l1 = GEN_TUPLE x_in (GEN_TUPLE new_output l1) 1778 val l2 = GEN_TUPLE x_in (GEN_TUPLE new_input l2) handle HOL_ERR _ => l2 1779 val goal = (fst o dest_imp o concl) thi 1780 val th = auto_prove "decompiler certificate" (goal, 1781 STRIP_TAC 1782 THEN1 (ONCE_REWRITE_TAC [simp_lemma] THEN REWRITE_TAC [] THEN 1783 REPEAT STRIP_TAC THEN MATCH_MP_TAC l2 THEN FULL_SIMP_TAC std_ss []) 1784 THEN1 (REPEAT STRIP_TAC THEN MATCH_MP_TAC l1 THEN FULL_SIMP_TAC std_ss [])) 1785 val th = MP thi th 1786 val th = SPEC x_in th 1787 val th = RW [GSYM SPEC_MOVE_COND] th 1788 val th = introduce_post_let th 1789 val th = INST [mk_var("()",``:unit``) |-> ``():unit``] th 1790 val th = 1791 th |> RW [SPEC_MOVE_COND] |> UNDISCH |> SIMP_RULE std_ss [SPEC_PRE_DISJ] 1792 |> CONJUNCTS |> hd |> DISCH_ALL |> RW [GSYM SPEC_MOVE_COND] 1793 val th = SPEC_ALL (SIMP_RULE bool_ss [SEP_CLAUSES,GSYM SPEC_PRE_EXISTS] th) 1794 val th = CONV_RULE (DEPTH_CONV DEST_NEW_VAR_CONV) th 1795 (* clean up and save function definitions *) 1796 val _ = delete_const (fst (dest_const step_const)) 1797 val _ = echo 1 " done.\n" 1798 val _ = save_thm(name ^ "_def",main_thm) 1799 val _ = save_thm(name ^ "_pre_def",pre_thm) 1800 in (th,main_thm,pre_thm) end; 1801 1802 1803(* -------------------------------------------------------------------------- *) 1804(* Implementation of STAGE 4 *) 1805(* -------------------------------------------------------------------------- *) 1806 1807fun prepare_for_reuse [] (th,i,j) k = [] 1808 | prepare_for_reuse (n::ns) (th,i,j) k = let 1809 val prefix = "new@" 1810 val th = ABBREV_CALL prefix th 1811 val mk_num = numSyntax.mk_numeral o Arbnum.fromInt 1812 val th = SIMP_RULE std_ss [] (INST [mk_var("pos",``:num``) |-> mk_num k] th) 1813 in (n,(th,i,j),NONE) :: prepare_for_reuse ns (th,i,j) (k+1) end; 1814 1815fun decompile_part name thms (entry,exit) 1816 (function_in_out: (term * term) option) = let 1817 val t = generate_spectree thms (entry,exit) 1818 val th = merge_spectree name t 1819 val (th,def,pre) = extract_function name th entry exit function_in_out 1820 val (th,pre) = simplify_pre pre th 1821 val (th,def) = (!decompiler_finalise) (th,def) 1822 val def = modifier "func" def 1823 in (def,pre,th) end; 1824 1825val fio = (NONE: (term * term) option) 1826 1827fun decompile_io_with q (tools :decompiler_tools) name fio code = 1828let 1829 val _ = set_tools tools 1830 val (thms,loops) = stage_12 name tools (q code) 1831 fun decompile_all thms (defs,pres) [] prev = 1832 (LIST_CONJ defs,LIST_CONJ pres,prev) 1833 | decompile_all thms (defs,pres) ((entry,exit)::loops) prev = let 1834(* 1835 val (entry,exit)::loops = loops 1836*) 1837 val function_in_out = (NONE: (term * term) option) 1838 val suff = int_to_string (length loops) 1839 val (part_name,function_in_out) = if length loops = 0 then (name,fio) 1840 else (name ^ suff,function_in_out) 1841 val (def,pre,result) = 1842 decompile_part part_name thms (entry,exit) function_in_out 1843 val thms = prepare_for_reuse entry (result,0,SOME (hd exit)) 0 @ thms 1844 in decompile_all thms (def::defs,pre::pres) loops result end 1845 val (def,pre,result) = decompile_all thms ([],[]) loops TRUTH 1846 val exit = snd (last loops) 1847 val _ = add_decompiled (name,result,hd exit,SOME (hd exit)) 1848 val result = if (get_abbreviate_code()) then result 1849 else UNABBREV_CODE_RULE result 1850 val func = RW [GSYM CONJ_ASSOC] (CONJ def pre) 1851 in (result,func) end; 1852 1853fun decompile_with q tools name code = decompile_io_with q tools name NONE code; 1854 1855val decompile_io = 1856 decompile_io_with (helperLib.quote_to_strings: term quotation -> string list) 1857 1858val decompile = 1859 decompile_with (helperLib.quote_to_strings: string quotation -> string list) 1860 1861val decompile_io_strings = decompile_io_with I 1862val decompile_strings = decompile_with I 1863 1864fun basic_decompile_with q (tools :decompiler_tools) name function_in_out code = 1865let 1866 val _ = set_tools tools 1867 val (thms,loops) = stage_12 name tools (q code) 1868 val (entry,exit) = (fn (x,y) => (hd x, hd y)) (last loops) 1869 val (entry,exit) = ([entry],[exit]) 1870 val (def,pre,result) = decompile_part name thms (entry,exit) function_in_out 1871 val _ = add_decompiled (name,result,hd exit,SOME (hd exit)) 1872 val result = 1873 if (get_abbreviate_code()) then result else UNABBREV_CODE_RULE result 1874 in (result,CONJ def pre) end; 1875 1876val basic_decompile = 1877 basic_decompile_with 1878 (helperLib.quote_to_strings: term quotation -> string list) 1879 1880val basic_decompile_strings = basic_decompile_with I 1881 1882end 1883