1structure separationLogicLib :> separationLogicLib = 2struct 3 4(* 5quietdec := true; 6loadPath := 7 (Globals.HOLDIR ^ "/examples/separationLogic/src") :: 8 (Globals.HOLDIR ^ "/examples/separationLogic/src/holfoot") :: 9 !loadPath; 10show_assums := true; 11*) 12 13open HolKernel Parse boolLib bossLib; 14open listTheory rich_listTheory 15open separationLogicTheory; 16open separationLogicSyntax 17open vars_as_resourceTheory 18open quantHeuristicsLib 19open quantHeuristicsLibBase 20open ConseqConv 21open Profile 22 23(* 24quietdec := false; 25*) 26 27 28(*Aplies functional equality (FUN_EQ_THM 29 |- (f = g) <=> !x. f x = g x) to 30 replace allquantified variables in 31 equations with lambda abstractions. 32 For example 33 34val t = ``!a b c. f a b c = g a b c`` 35 36 is converted to 37 38``f = (\a b c. g a b c)`` 39 40 This conversion can be used to preprocess 41 rewrite rules, allowing the rewriter to 42 use these rules, even if not all parameters are 43 present, yet.*) 44 45fun GSYM_FUN_EQ_CONV t = 46let 47 val (vars, b_term) = strip_forall t; 48 val (l_term,r_term) = dest_eq b_term; 49 val (l_f, l_args) = strip_comb l_term; 50 fun split_vars [] acc = ([], acc) 51 | split_vars (t::ts) acc = 52 if mem t vars then 53 split_vars ts (t::acc) 54 else 55 (rev (t::ts), acc) 56 val (rest_args, elim_args) = split_vars (rev l_args) []; 57 val _ = if (elim_args = []) then raise UNCHANGED else (); 58 val rest_vars = filter (fn v => not (mem v elim_args)) vars; 59 60 val l_term' = list_mk_comb (l_f, rest_args); 61 val r_term' = list_mk_abs (elim_args, r_term); 62 val b_term' = mk_eq (l_term', r_term'); 63 val t' = list_mk_forall (rest_vars, b_term'); 64 65 val thm_term = mk_eq (t,t'); 66 val thm = prove (thm_term, SIMP_TAC std_ss [FUN_EQ_THM] THEN 67 EQ_TAC THEN SIMP_TAC std_ss []) 68in 69 thm 70end 71 72 73 74(*Given a theorem of the form |- l = r it returns a theorem 75 r |- l. If r is T, then |- l is returned *) 76fun EQ_ELIM thm = 77 let 78 val (l,r) = dest_eq (concl thm); 79 in 80 if (same_const r T) then EQT_ELIM thm else 81 EQ_MP (GSYM thm) (ASSUME r) 82 end 83 84(*Applies a conversion to the rhs of an equational theorem*) 85fun RHS_CONV_RULE conv thm = 86((CONV_RULE (RHS_CONV conv)) thm) handle UNCHANGED => thm; 87 88(*Applies a conversion to the antecedent of an implication*) 89val ANTE_CONV = (RATOR_CONV o RAND_CONV); 90fun ANTE_CONV_RULE conv thm = ((CONV_RULE o ANTE_CONV) conv) thm 91 handle UNCHANGED => thm; 92 93 94 95(*************************************************************** 96 * PROGRAM ABSTRACTION 97 * 98 * The following functions are intended to abstract programs. 99 * A typical one of these functions has the following signature 100 * 101 * abst_function sys xenv penv prog 102 * 103 * given a program prog, this functions tries to find an abstration 104 * prog' and return a theorem of the form 105 * 106 * |- ASL_PROGRAM_IS_ABSTRACTION xenv penv prog prog' 107 * 108 * The parameter sys is a call to the system to ask it to abstract 109 * subprograms. It has the signature sys xenv penv prog. 110 * Calls to system never may fail, i.e. no useful abstraction can be found. 111 * In this case NONE is returned. Notice that 112 * prove_ASL_PROGRAM_ABSTRACTION_REFL may be used to produce 113 * |- ASL_PROGRAM_IS_ABSTRACTION xenv penv prog prog. 114 * 115 * If abst_function can not find an abstraction it should return NONE, 116 * throw an UNCHANGED exception or an HOL_ERR exception. 117 * 118 * There are abst_functions for the most common program constructs. 119 * Instantions of the framework might need to provide additional ones. 120 * These abstraction functions are combined by 121 * search_ASL_PROGRAM_ABSTRACTION fL abstL xenv penv prog 122 * 123 * - fL 124 * a list of abst_functions 125 * - abstL 126 * a list of already know abstraction, i.e. theorems of the form 127 * something? |- ASL_PROGRAM_IS_ABSTRACTION xnev penv prog1 prog2 128 ****************************************************************) 129 130 131fun prove_ASL_PROGRAM_ABSTRACTION_REFL xenv penv p = 132 (ISPECL [xenv,penv,p] ASL_PROGRAM_IS_ABSTRACTION___REFL); 133 134 135type simple_asl_program_abstraction = term -> term -> term -> thm option; 136type asl_program_abstraction = (term -> term) -> thm list -> simple_asl_program_abstraction -> simple_asl_program_abstraction; 137 138 139local 140(* 141 fun check_thm_opt xenv penv p NONE = NONE 142 | check_thm_opt xenv penv p (SOME thm) = 143 let 144 val (xenv', penv', p', _) = dest_ASL_PROGRAM_IS_ABSTRACTION (concl thm); 145 in 146 if (xenv = xenv') andalso 147 (penv = penv') andalso (p = p') then SOME thm else 148 let 149 val ps = (term_to_string p); 150 val xenvs = term_to_string xenv; 151 val penvs = term_to_string penv; 152 val thms = thm_to_string thm; 153 val s = "Abstraction of "^ps^ 154 " in ("^xenvs^","^penvs^") resulted in "^ 155 thms^"!"; 156 val _ = print s; 157 in 158 NONE 159 end 160 end; 161*) 162 fun check_thm_opt xenv penv p thm_opt = thm_opt 163 164 fun search_ASL_PROGRAM_ABSTRACTION_int (pf:term->term) true fL orgfL cref abstL xenv penv p = 165 let 166 val p_thm_opt_opt = Redblackmap.peek (!cref, p); 167 val thm_opt = 168 if (isSome p_thm_opt_opt) then ( 169 (valOf p_thm_opt_opt) 170 ) else ( 171 let 172 val thm1_opt = search_ASL_PROGRAM_ABSTRACTION_int pf false fL orgfL cref abstL xenv penv p; 173 val nc = Redblackmap.insert (!cref, p, thm1_opt) 174 val _ = cref := nc 175 in 176 thm1_opt 177 end 178 ) 179 in 180 check_thm_opt xenv penv p thm_opt 181 end 182 | search_ASL_PROGRAM_ABSTRACTION_int pf false [] orgfL cref abstL xenv penv p = NONE 183 | search_ASL_PROGRAM_ABSTRACTION_int pf false (f1::fL) orgfL cref abstL xenv penv p = 184 let 185 val sys = search_ASL_PROGRAM_ABSTRACTION_int pf true orgfL orgfL cref abstL; 186 val thm1_opt = ((f1 pf abstL sys xenv penv p) 187 handle HOL_ERR _ => NONE) 188 handle UNCHANGED => NONE; 189 in 190 if not (isSome thm1_opt) then 191 search_ASL_PROGRAM_ABSTRACTION_int pf false fL orgfL cref abstL xenv penv p 192 else 193 check_thm_opt xenv penv p thm1_opt 194 end; 195in 196 fun search_ASL_PROGRAM_ABSTRACTION pf (fL:asl_program_abstraction list) abstL (xenv:term) (penv:term) = 197 let 198 val cref = ref (Redblackmap.mkDict (Term.compare)) 199 val abstL' = (flatten (map BODY_CONJUNCTS abstL)); 200 val sys = search_ASL_PROGRAM_ABSTRACTION_int pf true fL fL cref abstL' xenv penv; 201 202 fun search p = 203 let 204 val thm_opt = sys p; 205 in 206 if not (isSome thm_opt) then NONE else 207 let 208 val thm1 = valOf thm_opt; 209 val (_,_,_,p') = dest_ASL_PROGRAM_IS_ABSTRACTION (concl thm1); 210 val thm2_opt = search p'; 211 in 212 if not(isSome thm2_opt) then thm_opt else 213 SOME (MATCH_MP (MATCH_MP 214 ASL_PROGRAM_IS_ABSTRACTION___TRANSITIVE thm1) 215 (valOf thm2_opt)) 216 end 217 end 218 in 219 search 220 end 221end; 222 223 224 225(* 226val thmL = BODY_CONJUNCTS (ASSUME proc_abst_t) 227val t = ``asl_prog_procedure_call "merge" ([],[]):holfoot_program`` 228*) 229 230fun ASL_PROGRAM_ABSTRACTION___match thmL sys xenv penv t = 231 let 232 val part = list_mk_icomb (ASL_PROGRAM_IS_ABSTRACTION_term, [xenv, penv, t]); 233 in 234 (tryfind (fn thm => SOME (PART_MATCH rator thm part)) thmL) 235 handle HOL_ERR _ => raise UNCHANGED 236 end; 237 238(* 239fun ASL_PROGRAM_ABSTRACTION___match thmL sys xenv penv t = 240 let 241 fun check_thm thm = 242 let 243 val (xenv', penv', p, p') = dest_ASL_PROGRAM_IS_ABSTRACTION t; 244 val m = match_term p t; 245 val _ = if (aconv xenv xenv') then () else fail(); 246 val _ = if (aconv penv penv') then () else fail(); 247 in 248 INST_TY_TERM m thm 249 end; 250 in 251 (tryfind check_thm thmL) 252 handle HOL_ERR _ => raise UNCHANGED 253 end; 254*) 255 256 257(* 258fun sys xenv penv t = NONE:thm option; 259val xenv = ``xenv :'a bin_option_function # ('b -> 'a -> bool)`` 260val penv = ``penv :'c |-> ('d -> ('d, 'b, 'c, 'a) asl_program)`` 261val p = ``(asl_prog_block (p1::pL)):('d, 'b, 'c, 'a) asl_program`` 262*) 263 264fun ASL_PROGRAM_ABSTRACTION___block pf abstL sys xenv penv p = 265 let 266 (*destruct block*) 267 val bodyL = dest_asl_prog_block p; 268 val (h,restBodyL) = listSyntax.dest_cons bodyL handle HOL_ERR _ => raise UNCHANGED; 269 270 (*Abstract parts*) 271 val thm_h_opt = sys xenv penv h; 272 val rest = mk_asl_prog_block restBodyL; 273 val thm_rest_opt = sys xenv penv rest; 274 275 (*Has something been achived? If not abort*) 276 val _ = if (not (isSome thm_h_opt) andalso not (isSome thm_rest_opt)) then raise UNCHANGED else (); 277 278 (*create dummy abstractions if needed*) 279 val thm_h = if (isSome thm_h_opt) then valOf thm_h_opt else 280 prove_ASL_PROGRAM_ABSTRACTION_REFL xenv penv h; 281 val thm_rest = if (isSome thm_rest_opt) then valOf thm_rest_opt else 282 prove_ASL_PROGRAM_ABSTRACTION_REFL xenv penv rest; 283 284 (*make sure the second abstraction is again a block, 285 if necessary create one*) 286 val (_, _, _, p1) = dest_ASL_PROGRAM_IS_ABSTRACTION (concl thm_h); 287 val (_, _, _, p2) = dest_ASL_PROGRAM_IS_ABSTRACTION (concl thm_rest); 288 289 val (thm_rest', pL) = if (is_asl_prog_block p2) then (thm_rest, dest_asl_prog_block p2) else 290 let 291 val pL = listSyntax.mk_list ([p2], type_of p2); 292 val thm_rest' = ONCE_REWRITE_RULE [GSYM ASL_PROGRAM_IS_ABSTRACTION___block_intro] thm_rest; 293 in 294 (thm_rest', pL) 295 end; 296 297 (* instantiate everything*) 298 val thm = ISPECL [xenv, penv, h, restBodyL,p1,pL] ASL_PROGRAM_IS_ABSTRACTION___block; 299 val thm1 = MP thm thm_h 300 val thm2 = MP thm1 thm_rest' 301 in 302 SOME thm2 303 end; 304 305 306(* 307fun sys xenv penv t = NONE:thm option; 308val xenv = ``xenv :'a bin_option_function # ('b -> 'a -> bool)`` 309val penv = ``penv :'c |-> ('d -> ('d, 'b, 'c, 'a) asl_program)`` 310val p = ``(asl_prog_block (p1::(asl_prog_block L)::p3::L')):('d, 'b, 'c, 'a) asl_program`` 311*) 312 313val append_thm_comment_nil1 = prove (`` 314 (asl_comment_location c []) ++ h::hs = 315 (asl_comment_location c (h:'a))::hs``, REWRITE_TAC[asl_comment_location_def, APPEND]) 316fun is_comment_nil t = 317 listSyntax.is_nil (#3 (dest_asl_comment t)) handle HOL_ERR _ => false 318 319val append_thm_nil1 = CONJUNCT1 APPEND 320val append_thm_nil2 = CONJUNCT1 APPEND_NIL 321val append_thm_cons = CONJUNCT2 APPEND 322 323fun list_append_norm_CONV tt = 324let 325 val (l1,l2) = listSyntax.dest_append tt; 326in 327 if ((listSyntax.is_append l1) orelse (listSyntax.is_append l2)) then 328 (((RATOR_CONV o RAND_CONV) list_append_norm_CONV) THENC 329 ((RAND_CONV) list_append_norm_CONV) THENC 330 list_append_norm_CONV) tt 331 else if (listSyntax.is_nil l1) then 332 ISPEC l2 append_thm_nil1 333 else if (listSyntax.is_nil l2) then 334 ISPEC l1 append_thm_nil2 335 else if (is_comment_nil l1) then 336 REWR_CONV append_thm_comment_nil1 tt 337 else let 338 val (h, l1') = listSyntax.dest_cons l1; 339 val thm0 = ISPECL [l1', l2, h] append_thm_cons 340 val thm1 = CONV_RULE (RHS_CONV (RAND_CONV list_append_norm_CONV)) thm0 341 in 342 thm1 343 end 344end handle HOL_ERR _ => raise UNCHANGED; 345 346 347 348fun ASL_PROGRAM_ABSTRACTION___block_flatten pf abstL sys xenv penv p = 349 let 350 (* destruct input *) 351 val bodyL = dest_asl_prog_block p; 352 val (body_termL,body_term_rest) = listSyntax.strip_cons bodyL handle HOL_ERR _ => raise UNCHANGED; 353 val body_term_type = listSyntax.dest_list_type (type_of body_term_rest) 354 355 (* find another block *) 356 val pos = index is_asl_prog_block body_termL 357 handle HOL_ERR _ => raise UNCHANGED; 358 359 (* split into the list before and after the found block *) 360 val L1_termL = List.take (body_termL,pos) 361 val L1_term = listSyntax.mk_list (L1_termL, body_term_type); 362 363 val L23_termL = List.drop (body_termL,pos); 364 val L2_term = dest_asl_prog_block (hd L23_termL); 365 366 val L3_termL = tl L23_termL; 367 val L3_term = itlist (curry listSyntax.mk_cons) L3_termL body_term_rest; 368 369 (*instantiate the corresponding theorem *) 370 val thm0 = ISPECL [xenv, penv, L1_term, L2_term, L3_term] ASL_PROGRAM_IS_ABSTRACTION___block_flatten; 371 372 (*However, this theorem contains append, it needs to be normalised*) 373 val (_,_,orgL, newL) = dest_ASL_PROGRAM_IS_ABSTRACTION (concl thm0); 374 375 val orgL_thm = (RAND_CONV list_append_norm_CONV) orgL; 376 val newL_thm = (RAND_CONV list_append_norm_CONV) newL; 377 378 val thm1 = CONV_RULE 379 (((RATOR_CONV o RAND_CONV) (K orgL_thm)) THENC 380 (RAND_CONV (K newL_thm))) thm0 381 in 382 SOME thm1 383 end; 384 385 386val ASL_PROGRAM_ABSTRACTION___block_flatten___no_rec = 387 ASL_PROGRAM_ABSTRACTION___block_flatten I [] (fn x => NONE) 388 389(* 390fun sys xenv penv t = NONE:thm option; 391val xenv = ``xenv :'a bin_option_function # ('b -> 'a -> bool)`` 392val penv = ``penv :'c |-> ('d -> ('d, 'b, 'c, 'a) asl_program)`` 393val p = ``(asl_prog_cond c p1 p2):('d, 'b, 'c, 'a) asl_program`` 394*) 395fun ASL_PROGRAM_ABSTRACTION___cond pf abstL sys xenv penv p = 396 let 397 (*destruct*) 398 val (c,p1,p2) = dest_asl_prog_cond p; 399 400 (*search abstractions*) 401 val p1_thm_opt = sys xenv penv p1; 402 val p2_thm_opt = sys xenv penv p2; 403 404 (*found something?*) 405 val _ = if (not (isSome p1_thm_opt) andalso not (isSome p2_thm_opt)) then raise UNCHANGED else (); 406 val p1_thm = if (isSome p1_thm_opt) then valOf p1_thm_opt else 407 prove_ASL_PROGRAM_ABSTRACTION_REFL xenv penv p1; 408 val p2_thm = if (isSome p2_thm_opt) then valOf p2_thm_opt else 409 prove_ASL_PROGRAM_ABSTRACTION_REFL xenv penv p2; 410 411 412 (*prove the final theorem*) 413 val (_,_,_,p1') = dest_ASL_PROGRAM_IS_ABSTRACTION (concl p1_thm); 414 val (_,_,_,p2') = dest_ASL_PROGRAM_IS_ABSTRACTION (concl p2_thm); 415 416 val thm = ISPECL [xenv, penv, c, p1,p1',p2,p2'] ASL_PROGRAM_IS_ABSTRACTION___cond; 417 val thm1 = MP thm p1_thm 418 val thm2 = MP thm1 p2_thm 419 in 420 SOME thm2 421 end; 422 423 424(* 425fun sys xenv penv t = SOME (prove_ASL_PROGRAM_ABSTRACTION_REFL xenv penv t) 426fun sys xenv penv t = NONE:thm option; 427val xenv = ``xenv :'a bin_option_function # ('b -> 'a -> bool)`` 428val penv = ``penv :'c |-> ('d -> ('d, 'b, 'c, 'a) asl_program)`` 429val p = ``(asl_prog_while c p):('d, 'b, 'c, 'a) asl_program`` 430*) 431fun ASL_PROGRAM_ABSTRACTION___while pf abstL sys xenv penv p = 432 let 433 val (c,p) = dest_asl_prog_while p; 434 435 (*search abstraction*) 436 val p_thm_opt = sys xenv penv p; 437 val p_thm = if (isSome p_thm_opt) then valOf p_thm_opt else raise UNCHANGED; 438 val (_,_,_,p') = dest_ASL_PROGRAM_IS_ABSTRACTION (concl p_thm); 439 440 val thm = ISPECL [xenv, penv, c, p,p'] ASL_PROGRAM_IS_ABSTRACTION___while; 441 val thm1 = MP thm p_thm; 442 in 443 SOME thm1 444 end; 445 446fun ASL_PROGRAM_ABSTRACTION___comment pf abstL sys xenv penv p = 447 let 448 val (_, c, p', def_thm) = dest_asl_comment p; 449 450 (*search abstraction*) 451 val p_thm_opt = sys xenv penv p'; 452 val p_thm = if (isSome p_thm_opt) then valOf p_thm_opt else raise UNCHANGED; 453 454 val (_,_,_,p'') = dest_ASL_PROGRAM_IS_ABSTRACTION (concl p_thm); 455 val thm_p' = ISPECL [c, p'] def_thm 456 val thm_p'' = ISPECL [c, p''] def_thm 457 458 val thm0 = CONV_RULE ((RAND_CONV) (K (GSYM thm_p''))) p_thm 459 val thm1 = CONV_RULE ((RATOR_CONV o RAND_CONV) (K (GSYM thm_p'))) thm0 460 in 461 SOME thm1 462 end; 463 464 465val basic_asl_program_abstractions = [ 466 ASL_PROGRAM_ABSTRACTION___block_flatten, 467 ASL_PROGRAM_ABSTRACTION___block, 468 ASL_PROGRAM_ABSTRACTION___cond, 469 ASL_PROGRAM_ABSTRACTION___comment, 470 ASL_PROGRAM_ABSTRACTION___while]:asl_program_abstraction list; 471 472 473(* 474 475val fL = append basic_asl_program_abstractions [ 476 ASL_PROGRAM_ABSTRACTION___local_var, 477 ASL_PROGRAM_ABSTRACTION___call_by_value_arg, 478 ASL_PROGRAM_ABSTRACTION___eval_expressions] 479 480val t = rand (snd (strip_forall (el 1 (strip_conj specs_t)))) 481val abstL = [ASSUME proc_abst_t] 482 483*) 484 485fun ASL_PROGRAM_HOARE_TRIPLE___ABSTRACTION___CONSEQ_CONV fL abstL t = 486 let 487 val _ = if (is_ASL_PROGRAM_HOARE_TRIPLE t) then () else raise UNCHANGED; 488 val (xenv, penv, pre, body, post) = dest_ASL_PROGRAM_HOARE_TRIPLE t; 489 490 val thm_opt = search_ASL_PROGRAM_ABSTRACTION I fL abstL xenv penv body; 491 val thm = if (isSome thm_opt) then valOf thm_opt else raise UNCHANGED; 492 493 val thm2 = ISPECL [xenv, penv, pre, body, post] ASL_PROGRAM_HOARE_TRIPLE_ABSTRACTION___INTRO; 494 val thm3 = MATCH_MP thm2 thm; 495 in 496 thm3 497 end; 498 499 500(* 501 val t = ``ASL_PROGRAM_IS_ABSTRACTION xenv penv p1 p2`` 502 503 val SOME (fL, abstL, t) = !t_opt 504 505*) 506 507fun ASL_PROGRAM_IS_ABSTRACTION___ABSTRACTION___CONSEQ_CONV fL abstL t = 508 let 509 val (xenv, penv, p1, p3) = dest_ASL_PROGRAM_IS_ABSTRACTION t handle HOL_ERR _ => raise UNCHANGED 510 511 val print_fun = 512 let 513 val (a1, a2, _, x) = dest_asl_procedure_call_preserve_names_wrapper 514 (find_term is_asl_procedure_call_preserve_names_wrapper p3) 515 val (x1,x2) = pairSyntax.dest_pair x; 516 fun mk_list_term x a = 517 let 518 val ty = listSyntax.dest_list_type (type_of x) 519 val sL = map (fst o dest_var) (fst (listSyntax.dest_list a)) 520 val vL = map (fn s => mk_var (s, ty)) sL; 521 in 522 listSyntax.mk_list (vL, ty) 523 end; 524 val l1 = mk_list_term x1 a1; 525 val l2 = mk_list_term x2 a2 526 val su = subst [x1 |-> l1, x2 |-> l2] 527 in 528 fn p1 => (rhs (concl (SIMP_CONV list_ss [] (su p1)))) handle UNCHANGED => su p1 529 end handle UNCHANGED => I 530 | HOL_ERR _ => I 531 532 val thm_opt = search_ASL_PROGRAM_ABSTRACTION print_fun fL abstL xenv penv p1; 533 val thm = if (isSome thm_opt) then valOf thm_opt else raise UNCHANGED; 534 535 val (_, _, _, p2) = dest_ASL_PROGRAM_IS_ABSTRACTION (concl thm); 536 537 val thm2 = ISPECL [xenv, penv, p1, p2, p3] ASL_PROGRAM_IS_ABSTRACTION___TRANSITIVE; 538 val thm3 = MP thm2 thm; 539 in 540 thm3 541 end; 542 543 544 545 546 547(*************************************************************** 548 * HANDLE SPECIFICATIONS 549 * 550 * Elininate function calls 551 ****************************************************************) 552 553 554val names_all_distinct_cs = computeLib.bool_compset (); 555val _ = computeLib.add_thms [listTheory.MAP, pairTheory.FST, pairTheory.SND, 556 listTheory.ALL_DISTINCT, 557 listTheory.MEM] names_all_distinct_cs; 558val _ = computeLib.add_conv (``($=):'a -> 'a -> bool``, 2, stringLib.string_EQ_CONV) names_all_distinct_cs; 559 560 561 562val proc_free_specs_cs = computeLib.bool_compset (); 563val _ = computeLib.add_thms [listTheory.EVERY_DEF, pairTheory.SND, pairTheory.FST, 564 REWRITE_RULE [asl_prog_IS_RESOURCE_AND_PROCCALL_FREE___ALTERNATIVE_DEF] asl_prog_IS_RESOURCE_AND_PROCCALL_FREE___prim_command, 565 REWRITE_RULE [asl_prog_IS_RESOURCE_AND_PROCCALL_FREE___ALTERNATIVE_DEF] asl_prog_IS_RESOURCE_AND_PROCCALL_FREE___SIMPLE_REWRITES] proc_free_specs_cs; 566val _ = computeLib.add_conv (pairSyntax.uncurry_tm, 2, pairLib.GEN_BETA_CONV) proc_free_specs_cs; 567 568 569 570(* 571fun proc_call_free_CONV t = REWRITE_CONV [ 572 REWRITE_RULE [asl_prog_IS_RESOURCE_AND_PROCCALL_FREE___ALTERNATIVE_DEF] 573 asl_prog_IS_RESOURCE_AND_PROCCALL_FREE___var_res_bla] t; 574 575val prog_rewrites = [var_res_prog_procedure_call_THM] 576 577val abstrL = append basic_asl_program_abstractions [ 578 ASL_PROGRAM_ABSTRACTION___local_var, 579 ASL_PROGRAM_ABSTRACTION___call_by_value_arg, 580 ASL_PROGRAM_ABSTRACTION___eval_expressions] 581 582 val thm_strengthen_specs = 583 DEPTH_CONSEQ_CONV (ASL_PROGRAM_IS_ABSTRACTION___ABSTRACTION___CONSEQ_CONV abstrL [ASSUME proc_abst_t]) 584 specs_t 585 586val t = ``asl_comment_location_string "XXX" YYY`` 587*) 588fun asl_comment_location_string_ELIM_CONV t = 589let 590 val (c, p) = dest_asl_comment_location_string t 591 val c_label = mk_var(stringLib.fromHOLstring c, markerSyntax.label_ty) 592 val c_list = listSyntax.mk_list ([c_label], markerSyntax.label_ty) 593 594 val thm1 = ISPECL [c,p] asl_comment_location_string_def 595 val thm2 = GSYM (ISPECL [c_list, p] asl_comment_location_def) 596in 597 TRANS thm1 thm2 598end; 599 600 601val precond1_cs = computeLib.bool_compset (); 602val _ = computeLib.add_thms [listTheory.EVERY_DEF, 603 pairTheory.FST, pairTheory.SND] precond1_cs; 604val _ = computeLib.add_conv (pairSyntax.uncurry_tm, 2, pairLib.GEN_BETA_CONV) precond1_cs; 605val _ = computeLib.add_conv (asl_comment_location_string_term, 2, asl_comment_location_string_ELIM_CONV) precond1_cs; 606 607 608val precond1_conv = 609 (QUANT_INSTANTIATE_CONV [pair_default_qp]) THENC 610 DEPTH_CONV (pairLib.GEN_BETA_CONV) 611 612 613 614fun ASL_SPECIFICATION___CONSEQ_CONV (proc_call_free_CONV, abstrL) t = 615let 616 (* apply SPECIFICATION INFERENCE *) 617 fun apply_inference_rule t = 618 let 619 val (f_term, res_decls_term, p_specs_term) = dest_ASL_SPECIFICATION t; 620 val thm1 = ISPECL [f_term, res_decls_term, p_specs_term] ASL_INFERENCE___SPECIFICATION; 621 622 val side_conds_term = fst (dest_imp (concl thm1)); 623 val (proc_free_specs_term, distinct_proc_names_term) = dest_conj side_conds_term; 624 625 626 val proc_free_specs_thm = EQ_ELIM ((computeLib.CBV_CONV proc_free_specs_cs THENC 627 proc_call_free_CONV) proc_free_specs_term) handle HOL_ERR _ => 628 failwith ("Could not prove that specifications are well formed!"); 629 630 val distinct_proc_names_thm = EQ_ELIM (computeLib.CBV_CONV names_all_distinct_cs distinct_proc_names_term) handle HOL_ERR _ => 631 failwith ("Could not prove that all procedure names are distinct!"); 632 633 val thm2 = MP thm1 (CONJ proc_free_specs_thm distinct_proc_names_thm); 634 in 635 thm2 636 end; 637 638 639 640 (*Simplify*) 641 fun simplify_precond thm = 642 let 643 val thm1 = CONV_RULE (RATOR_CONV (RAND_CONV (computeLib.CBV_CONV precond1_cs))) thm; 644 val thm2 = CONV_RULE (RATOR_CONV (RAND_CONV (Conv.QUANT_CONV (RAND_CONV precond1_conv)))) thm1; 645 in 646 thm2 647 end; 648 649 650 651 652 (* Eliminate procedure calls, locks, etc. *) 653 fun eliminate_environment thm = 654 let 655 val precond = fst (dest_imp (concl thm)); 656 val (penv_var, body) = dest_forall precond; 657 val (proc_abst_t, specs_t) = dest_imp body; 658 659 val thm_strengthen_specs = 660 DEPTH_STRENGTHEN_CONSEQ_CONV (ASL_PROGRAM_IS_ABSTRACTION___ABSTRACTION___CONSEQ_CONV abstrL [ASSUME proc_abst_t]) 661 specs_t handle UNCHANGED => REFL_CONSEQ_CONV specs_t; 662 663 664 val thm2 = let 665 val precond' = fst (dest_imp (concl thm_strengthen_specs)); 666 val x_thm0 = ADD_ASSUM proc_abst_t (UNDISCH thm_strengthen_specs) 667 val x_thm1 = DISCH proc_abst_t x_thm0 668 val x_thm2 = DISCH precond' x_thm1 669 val x_thm3 = GEN_IMP penv_var x_thm2 670 val precond'' = fst (dest_imp (concl x_thm3)); 671 val x_thm4 = UNDISCH x_thm3 672 val x_thm5 = MP thm x_thm4 673 val x_thm6 = DISCH precond'' x_thm5 674 in x_thm6 end; 675 in 676 thm2 677 end; 678 679 680 681 val current_thm = apply_inference_rule t; 682 val current_thm2 = simplify_precond current_thm; 683 val current_thm3 = eliminate_environment current_thm2; 684in 685 current_thm3 686end; 687 688 689 690(******************************************************************************) 691(* Remove procedure_call_preserve_names_wrapper *) 692(******************************************************************************) 693 694(* 695val tt = ``asl_procedure_call_preserve_names_wrapper ["r"] 696 ["p_const"] c ([q],[x])`` 697*) 698 699fun asl_procedure_call_preserve_names_wrapper_ELIM_CONV tt = 700let 701 val thm0 = PART_MATCH (lhs o snd o dest_imp_only) 702 asl_procedure_call_preserve_names_wrapper_ELIM tt; 703 val precond = (fst o dest_imp o concl) thm0 704 val precond_thm = EQT_ELIM (REWRITE_CONV [LENGTH, 705 pairTheory.SND, pairTheory.FST] precond) 706in 707 MP thm0 precond_thm 708end; 709 710(******************************************************************************) 711(* HANDLE location comments *) 712(******************************************************************************) 713(* 714 val c = asl_comment_modify_INC c 715*) 716 717fun get_last_num_token c = 718let 719 val (la, cL) = listSyntax.dest_cons c 720 val s = fst (dest_var la) 721 722 val sL = String.tokens (fn c => c = #" ") s; 723 val ls = last sL; 724 725 val n_opt = Int.fromString ls 726 val (n, s') = if isSome n_opt then (valOf n_opt, String.concatWith " " (butlast sL)) 727 else (0, s) 728in 729 (n, s', cL, isSome n_opt) 730end handle HOL_ERR _ => (0, "", c, false) 731 732 733fun asl_comment_modify_NUM_OP f c = 734let 735 736 val (n, s', c', num_found) = get_last_num_token c 737 738 val ns = Int.toString (f n) 739 val s'' = s' ^ " " ^ ns; 740 val l = mk_var (s'', markerSyntax.label_ty) 741 val c'' = listSyntax.mk_cons (l, c') 742in 743 c'' 744end; 745 746fun asl_comment_modify_NUM_COPY_INIT i c = 747let 748 val (n, s', c', num_found) = get_last_num_token c 749in 750 if num_found then c else 751 let 752 val s'' = s' ^ " " ^ (Int.toString i); 753 val l = mk_var (s'', markerSyntax.label_ty) 754 val c'' = listSyntax.mk_cons (l, c') 755 in 756 c'' 757 end 758end; 759 760 761val asl_comment_modify_INC = 762 asl_comment_modify_NUM_OP (fn n => n+1); 763 764val asl_comment_modify_COPY_INIT = 765 asl_comment_modify_NUM_COPY_INIT 1; 766 767fun asl_comment_modify_APPEND s c = 768let 769 val l = mk_var (s, markerSyntax.label_ty) 770 val c' = listSyntax.mk_cons (l, c) 771in 772 c' 773end; 774 775 776fun asl_comment_modify_APPEND_INC s c = 777let 778 val (n, s', c',_) = get_last_num_token c 779 780 val c'' = listSyntax.mk_cons (mk_var 781 (s', markerSyntax.label_ty), c') 782 783 val ns = Int.toString (n + 1) 784 val s'' = s ^ " " ^ ns; 785 val c''' = listSyntax.mk_cons (mk_var 786 (s'', markerSyntax.label_ty), c'') 787in 788 c''' 789end; 790 791 792fun asl_comment_modify_APPEND_DEC s c = 793let 794 val (n, s', c',_) = get_last_num_token c 795 796 val c'' = listSyntax.mk_cons (mk_var 797 (s', markerSyntax.label_ty), c') 798 799 val ns = Int.toString (n - 1) 800 val s'' = s ^ " " ^ ns; 801 val c''' = listSyntax.mk_cons (mk_var 802 (s'', markerSyntax.label_ty), c'') 803in 804 c''' 805end; 806 807 808fun asl_comment_block_CONV conv t = 809 if (not (is_asl_prog_block t)) then conv t else 810 let 811 val pL = dest_asl_prog_block t; 812 val rec_call = asl_comment_block_CONV conv 813 in 814 if listSyntax.is_cons pL then 815 ((RAND_CONV o RATOR_CONV o RAND_CONV) rec_call) t 816 else if listSyntax.is_nil pL then 817 (RAND_CONV rec_call) t 818 else conv t 819 end; 820 821fun asl_comment_location_INTRO_CONV c t = 822 ISPECL [c, t] (GSYM asl_comment_location_def) 823 824fun asl_comment_location_BLOCK_INTRO_CONV c = 825 asl_comment_block_CONV (asl_comment_location_INTRO_CONV c) 826 827fun asl_comment_location2_INTRO_CONV c t = 828 ISPECL [c, t] (GSYM asl_comment_location2_def) 829 830fun asl_comment_abstraction_INTRO_CONV s t = 831 let 832 val l = mk_var (s, markerSyntax.label_ty); 833 in 834 ISPECL [l, t] (GSYM asl_comment_abstraction_def) 835 end; 836 837 838fun asl_comment_location_CONSEQ_RULE c thm = 839let 840 val _ = if is_eq (concl thm) orelse 841 is_imp_only (concl thm) then () else Feedback.fail (); 842in 843 CONV_RULE (BINOP_CONV (asl_comment_location_INTRO_CONV c)) thm 844end; 845 846 847fun asl_comment_location_CONSEQ_CONV conv t = 848let 849 val (c, t') = dest_asl_comment_location t; 850 val thm0 = conv t'; 851in 852 asl_comment_location_CONSEQ_RULE c thm0 853end; 854 855 856fun asl_comment_location___TF_ELIM___CONV t = 857let 858 val (c, t') = dest_asl_comment_location t; 859 val _ = if (aconv t' T) orelse (aconv t' F) then () else raise UNCHANGED; 860in 861 ISPECL [c, t'] asl_comment_location_def 862end; 863 864 865fun CONSEQ_CONV_CONGRUENCE___location_comment context sys dir t = 866 let 867 val (c, body) = dest_asl_comment_location t 868 val (n1, thm0_opt) = sys [] context 0 dir body; 869 val _ = if (isSome thm0_opt) then () else raise UNCHANGED; 870 871 val thm1 = asl_comment_location_CONSEQ_RULE c (valOf thm0_opt) 872 in 873 (n1, thm1) 874 end 875 876 877(******************************************************************************) 878(* Remove asl_exists_list *) 879(******************************************************************************) 880 881(* 882val tt = ``asl_exists_list [aa; bb; cc] (\x s. (sdds x /\ D /\ (LENGTH x = 3)))`` 883val tt = ttt 884val base_name = "name" 885val t2s = term_to_string 886val t2s = holfoot_term_to_string 887*) 888 889local 890 val conv_nil = REWR_CONV (CONJUNCT1 asl_exists_list___REWRITE) 891 val conv_cons = REWR_CONV (CONJUNCT2 asl_exists_list___REWRITE) 892 fun asl_exists_list_CONV_int [] = 893 conv_nil THENC (TRY_CONV BETA_CONV) 894 | asl_exists_list_CONV_int (n::ns) = 895 conv_cons THENC (RAND_CONV (RENAME_VARS_CONV [n])) THENC 896 RAND_CONV (ABS_CONV ( 897 (RAND_CONV (ABS_CONV (TRY_CONV BETA_CONV))) THENC 898 asl_exists_list_CONV_int ns)) 899in 900 901fun asl_exists_list_CONV base_name t2s tt = 902let 903 val (argL, P) = dest_asl_exists_list tt; 904 fun t2s' t = concat [base_name, "_", t2s t] 905 val namesL = map t2s' (fst (listSyntax.dest_list argL)) 906 val P_v = genvar (type_of P) 907 908 val new_t = list_mk_icomb (asl_exists_list_term, [argL, P_v]) 909 val thm0 = asl_exists_list_CONV_int namesL new_t; 910 val thm1 = INST [P_v |-> P] thm0 911 val thm2 = CONV_RULE (RHS_CONV (DEPTH_CONV BETA_CONV)) thm1 912in 913 thm2 914end; 915 916end; 917 918(* 919fun VAR_RES_LOCATION_COMMENT_step___CONV tt = 920let 921 val (c, body) = dest_asl_comment_location tt; 922in 923end 924*) 925 926 927 928 929(* 930open holfootParser 931open holfoot_pp_print 932val examplesDir = concat [Globals.HOLDIR, "/examples/separationLogic/src/holfoot/EXAMPLES/"] 933val file = concat [examplesDir, "mergesort.sf"]; 934val file = concat [examplesDir, "mergesort.dsf"]; 935val t = parse_holfoot_file file 936val t = parse_holfoot_file_restrict ["mergesort"] file 937 938temp_remove_holfoot_pp ();temp_add_holfoot_pp ();t 939temp_remove_holfoot_pp ();t 940 941 942 943open Profile 944add_holfoot_pp() 945reset_all (); 946val thm = time (ASL_SPECIFICATION___CONSEQ_CONV (proc_call_free_CONV, abstrL)) t; 947print_profile_results (results()); 948 949 950open Profile 951reset_all () 952print_profile_results (results()) 953val cref = 0 954 955*) 956 957 958 959end 960