1structure holfootParser :> holfootParser = 2struct 3 4(* 5quietdec := true; 6loadPath := 7 (concat [Globals.HOLDIR, "/examples/separationLogic/src"]) :: 8 (concat [Globals.HOLDIR, "/examples/separationLogic/src/holfoot"]) :: 9 !loadPath; 10 11map load ["finite_mapTheory", "holfootTheory", 12 "Parsetree", "AssembleHolfootParser"]; 13 14use (Globals.HOLDIR ^ "/examples/separationLogic/src/holfoot/hfheader.sml") 15 16show_assums := true; 17*) 18 19open HolKernel Parse boolLib finite_mapTheory 20open Parsetree; 21open separationLogicSyntax 22open vars_as_resourceSyntax 23open holfootSyntax 24 25(* 26quietdec := false; 27*) 28 29 30exception holfoot_unsupported_feature_exn of string; 31 32val list_data_tag = ref "hd"; 33val data_list_tag = ref "dta"; 34val array_data_tag = ref "dta"; 35val list_link_tag = ref "tl" 36val tree_data_tag = ref "dta" 37val tree_link_tags = ref ("l", "r") 38 39 40fun mk_el_list 0 v = [] 41 | mk_el_list n v = 42 (listSyntax.mk_hd v)::(mk_el_list (n-1) (listSyntax.mk_tl v)) 43 44fun mk_list [] = Absyn.mk_ident "NIL" 45 | mk_list (e::es) = 46 Absyn.mk_app (Absyn.mk_app (Absyn.mk_ident "CONS", e), mk_list es) 47 48fun absyn2term a = absyn_to_term (term_grammar ()) a 49 50fun string_to_label s = mk_var (s, markerSyntax.label_ty); 51 52val parse = AssembleHolfootParser.raw_read_file; 53 54 55(* 56val file = "/home/tuerk/Downloads/holfoot/EXAMPLES/business2.sf"; 57val file = "/home/tt291/Downloads/holfoot/EXAMPLES/business2.sf"; 58 59val prog = parse file; 60*) 61 62fun vstruct_idents s (Absyn.VAQ _) = s 63 | vstruct_idents s (Absyn.VIDENT (_, i)) = Redblackset.add (s, i) 64 | vstruct_idents s (Absyn.VPAIR (_, vs1, vs2)) = 65 vstruct_idents (vstruct_idents s vs1) vs2 66 | vstruct_idents s (Absyn.VTYPED (_, vs, _)) = 67 vstruct_idents s vs; 68 69 70fun map_ident (s,f,f2_opt,f3_opt) l = case l of 71 Absyn.AQ (locn,t) => (s, Absyn.AQ (locn,t)) 72 | Absyn.IDENT (locn,i) => 73 let 74 val (s', a) = f s locn i 75 in 76 (s', a) 77 end 78 | Absyn.QIDENT(locn,t,i) => (s, Absyn.QIDENT(locn,t,i)) 79 | Absyn.APP (locn,a1,a2) => 80 let 81 val (s', a1') = map_ident (s,f,f2_opt,f3_opt) a1 82 val (s'', a2') = map_ident (s',f,f2_opt,f3_opt) a2 83 in 84 (s'', Absyn.APP (locn,a1',a2')) 85 end 86 | Absyn.LAM (locn,v,a) => 87 let 88 val is = vstruct_idents (Redblackset.empty String.compare) v; 89 val s' = if isSome f2_opt then (valOf f2_opt) s locn is else s; 90 val (s'', a') = map_ident (s',f,f2_opt, f3_opt) a 91 val s''' = if isSome f3_opt then (valOf f3_opt) s'' locn is else s''; 92 in 93 (s''', Absyn.LAM (locn,v,a')) 94 end 95 | Absyn.TYPED (locn,a,p) => 96 let 97 val (s', a') = map_ident (s,f,f2_opt,f3_opt) a 98 in 99 (s', Absyn.TYPED (locn,a',p)) 100 end 101 102fun collect_ident l = 103let 104 val is = Redblackset.empty String.compare 105 fun col set l s = (Redblackset.add (set,s), Absyn.IDENT (l, s)) 106 fun del set l is = Redblackset.difference (set,is) 107 val (set, _) = map_ident (is, col,NONE, SOME del) l 108in 109 set 110end; 111 112 113fun string_list2set sL = 114 Redblackset.addList(Redblackset.empty String.compare, sL); 115 116 117fun is_holfoot_ex_ident i = 118 ((String.size i > 1) andalso 119 (String.sub (i,0) = #"_") andalso 120 not (String.sub (i,1) = #" ")); 121fun norm_holfoot_ex_ident i = String.substring(i, 1, (String.size i) - 1); 122 123local 124 fun subst_qv_ident qv l i = 125 if (is_holfoot_ex_ident i) then 126 let 127 val i' = norm_holfoot_ex_ident i; 128 val qv' = Redblackset.add (qv, i') 129 in 130 (qv', Absyn.IDENT (l, i')) 131 end else (qv, Absyn.IDENT (l, i)) 132in 133 134fun remove_qv a = 135 map_ident (Redblackset.empty String.compare, subst_qv_ident, NONE, NONE) a 136 137end; 138 139 140fun HOL_Absyn h = 141 let 142 val h' = String.translate (fn #"#" => "" | c => String.str c) h 143 val ha = Absyn [QUOTE h']; 144 in 145 ha 146 end; 147 148fun absyn_extract_vars vL a = 149 let 150 val eL_v = genvar (Type `:num list`); 151 val eL_L = mk_el_list (length vL) eL_v; 152 val substL = zip vL eL_L; 153 fun a_subst set l i = (if Redblackset.member (set, i) then Feedback.fail() else 154 (set, Absyn.mk_AQ (assoc i substL))) handle HOL_ERR _ => (set, Absyn.IDENT (l, i)) 155 fun my_union set l is = Redblackset.union (set, is); 156 val (_, a') = map_ident (Redblackset.empty String.compare, a_subst, SOME my_union, NONE) a 157 val qa = Absyn.mk_lam (Absyn.VAQ (locn.Loc_None, eL_v), a') 158 159 val vL' = map (fn v => mk_comb(holfoot_exp_var_term, string2holfoot_var v)) vL; 160 val vLt = listSyntax.mk_list (vL', holfoot_a_expression_ty); 161 in 162 (qa, vLt) 163 end; 164 165 166fun replace_old os_opt l = case l of 167 Absyn.AQ (locn,t) => (os_opt, l) 168 | Absyn.IDENT (locn,i) => (os_opt, l) 169 | Absyn.QIDENT(locn,t,i) => (os_opt, l) 170 | Absyn.APP (locn,Absyn.IDENT(_,"old"),Absyn.IDENT(_,v)) => 171 let 172 val os = if isSome os_opt then valOf os_opt else 173 Feedback.failwith ("No old value of "^v^" available here!"); 174 val nv_opt = Redblackmap.peek (os, v); 175 val (nv, os') = if isSome (nv_opt) then (valOf nv_opt, os) else 176 let 177 val nv = mk_var ("old_"^v, numLib.num); 178 val os' = Redblackmap.insert(os,v,nv); 179 in 180 (nv,os') 181 end; 182 in 183 (SOME os', Absyn.IDENT (locn,(fst o dest_var) nv)) 184 end 185 | Absyn.APP (locn,a1,a2) => 186 let 187 val (os_opt, a1') = replace_old os_opt a1 188 val (os_opt, a2') = replace_old os_opt a2 189 in 190 (os_opt, Absyn.APP (locn,a1',a2')) 191 end 192 | Absyn.LAM (locn,v,a) => 193 let 194 val (os_opt, a') = replace_old os_opt a 195 in 196 (os_opt, Absyn.LAM (locn,v,a')) 197 end 198 | Absyn.TYPED (locn,a,p) => 199 let 200 val (os_opt, a') = replace_old os_opt a 201 in 202 (os_opt, Absyn.TYPED (locn,a',p)) 203 end 204 205 206fun HOL_Absyn_old_vars vs (os_opt, cs_opt) h = 207let 208 val ha = HOL_Absyn h 209 210 val (os_opt, ha) = replace_old os_opt ha; 211 212 val (ha, cs_opt) = if (not (isSome cs_opt)) then (ha, NONE) else 213 let 214 val used_vars = Redblackset.intersection (collect_ident ha, fst vs); 215 fun const_name v = v^"_lc"; 216 fun my_union set l is = Redblackset.union (set, is); 217 fun my_work set l i = 218 let 219 val i' = if not (Redblackset.member (used_vars, i)) orelse 220 Redblackset.member (set,i) then i else 221 ("_"^(const_name i)) 222 in 223 (set, Absyn.IDENT (l, i')) 224 end 225 226 val (_, ha') = map_ident (Redblackset.empty String.compare, 227 my_work, SOME my_union, NONE) ha; 228 val used_varsL = Redblackset.listItems used_vars 229 val cs_opt' = SOME ( 230 List.foldl (fn (k,d) => Redblackmap.insert (d, k, 231 mk_var(const_name k, numLib.num))) (valOf cs_opt) used_varsL) 232 in 233 (ha', cs_opt') 234 end; 235in 236 ((os_opt, cs_opt), ha) 237end; 238 239 240fun holfoot_expression2absyn vs os_opt (Aexp_ident x) = 241 if (String.sub (x, 0) = #"#") then 242 (os_opt, Absyn.mk_app (Absyn.mk_AQ holfoot_exp_const_term, 243 Absyn.mk_ident (String.substring(x, 1, (String.size x) - 1)))) 244 else if (is_holfoot_ex_ident x) orelse (Redblackset.member (snd vs, x)) then 245 (os_opt, Absyn.mk_app (Absyn.mk_AQ holfoot_exp_const_term, 246 Absyn.mk_ident x)) 247 else 248 let 249 val var_term = string2holfoot_var x; 250 val term = mk_comb(holfoot_exp_var_term, var_term) 251 in 252 (os_opt, Absyn.mk_AQ term) 253 end 254| holfoot_expression2absyn vs os_opt (Aexp_old_ident x) = 255 let 256 val os = if isSome os_opt then valOf os_opt else 257 Feedback.failwith ("No old value of "^x^" available here!"); 258 val nv_opt = Redblackmap.peek (os, x); 259 val (nv, os') = if isSome (nv_opt) then (valOf nv_opt, os) else 260 let 261 val nv = mk_var ("old_"^x, numLib.num); 262 val os' = Redblackmap.insert(os,x,nv); 263 in 264 (nv,os') 265 end; 266 val et = mk_comb (holfoot_exp_const_term, nv); 267 in 268 (SOME os', Absyn.mk_AQ et) 269 end 270| holfoot_expression2absyn vs os_opt (Aexp_num n) = 271 (os_opt, Absyn.mk_AQ (mk_comb (holfoot_exp_const_term, numLib.term_of_int n))) 272| holfoot_expression2absyn vs os_opt (Aexp_infix (opstring, e1, e2)) = 273 let 274 val opterm = if (opstring = "-") then holfoot_exp_sub_term else 275 if (opstring = "+") then holfoot_exp_add_term else 276 if (opstring = "*") then holfoot_exp_mult_term else 277 if (opstring = "/") then holfoot_exp_div_term else 278 if (opstring = "%") then holfoot_exp_mod_term else 279 if (opstring = "^") then holfoot_exp_exp_term else 280 Raise (holfoot_unsupported_feature_exn ("Pexp_infix "^opstring)); 281 val (os_opt' , t1) = holfoot_expression2absyn vs os_opt e1; 282 val (os_opt'', t2) = holfoot_expression2absyn vs os_opt' e2; 283 in 284 (os_opt'', Absyn.list_mk_app (Absyn.mk_AQ opterm, [t1, t2])) 285 end 286| holfoot_expression2absyn vs os_opt (Aexp_hol h) = 287 let 288 val ((os_opt,_), ha) = HOL_Absyn_old_vars vs (os_opt,NONE) h; 289 val used_vars = Redblackset.listItems (Redblackset.intersection (collect_ident ha, fst vs)) 290 in 291 if (null used_vars) then 292 (os_opt, Absyn.mk_app (Absyn.mk_AQ holfoot_exp_const_term, ha)) 293 else 294 let 295 val (qha, vLt) = absyn_extract_vars used_vars ha 296 in 297 (os_opt, Absyn.list_mk_app (Absyn.mk_AQ holfoot_exp_op_term, [qha, Absyn.mk_AQ vLt])) 298 end 299 end; 300 301 302 303fun holfoot_p_condition2absyn vs Pcond_false = 304 Absyn.mk_AQ holfoot_pred_false_term 305| holfoot_p_condition2absyn vs Pcond_true = 306 Absyn.mk_AQ holfoot_pred_true_term 307| holfoot_p_condition2absyn vs (Pcond_neg c1) = 308 let 309 val t1 = holfoot_p_condition2absyn vs c1 310 in 311 (Absyn.mk_app (Absyn.mk_AQ holfoot_pred_neg_term, t1)) 312 end 313| holfoot_p_condition2absyn vs (Pcond_and (c1,c2)) = 314 let 315 val t1 = holfoot_p_condition2absyn vs c1 316 val t2 = holfoot_p_condition2absyn vs c2 317 in 318 (Absyn.list_mk_app (Absyn.mk_AQ holfoot_pred_and_term, [t1, t2])) 319 end 320| holfoot_p_condition2absyn vs (Pcond_or (c1,c2)) = 321 let 322 val t1 = holfoot_p_condition2absyn vs c1 323 val t2 = holfoot_p_condition2absyn vs c2 324 in 325 (Absyn.list_mk_app (Absyn.mk_AQ holfoot_pred_or_term, [t1, t2])) 326 end 327| holfoot_p_condition2absyn vs (Pcond_compare (opstring, e1, e2)) = 328 let 329 val opterm = if (opstring = "==") then holfoot_pred_eq_term else 330 if (opstring = "!=") then holfoot_pred_neq_term else 331 if (opstring = "<") then holfoot_pred_lt_term else 332 if (opstring = "<=") then holfoot_pred_le_term else 333 if (opstring = ">") then holfoot_pred_gt_term else 334 if (opstring = ">=") then holfoot_pred_ge_term else 335 Raise (holfoot_unsupported_feature_exn ("Pcond_compare "^opstring)); 336 val (_, t1) = holfoot_expression2absyn vs NONE e1; 337 val (_, t2) = holfoot_expression2absyn vs NONE e2; 338 in 339 (Absyn.list_mk_app (Absyn.mk_AQ opterm, [t1, t2])) 340 end 341| holfoot_p_condition2absyn vs (Pcond_hol h) = 342 let 343 val ha = HOL_Absyn h; 344 val used_vars = Redblackset.listItems (Redblackset.intersection (collect_ident ha, fst vs)) 345 in 346 let 347 val (qha, vLt) = absyn_extract_vars used_vars ha 348 in 349 Absyn.list_mk_app (Absyn.mk_AQ holfoot_pred_term, [qha, Absyn.mk_AQ vLt]) 350 end 351 end; 352 353 354 355val tag_a_expression_fmap_emp_term = ``FEMPTY:(holfoot_tag |-> holfoot_a_expression)``; 356val tag_a_expression_fmap_update_term = ``FUPDATE:(holfoot_tag |-> holfoot_a_expression)-> 357(holfoot_tag # holfoot_a_expression)->(holfoot_tag |-> holfoot_a_expression)``; 358 359 360fun tag_a_expression_list2absyn vs rvm [] = (rvm, Absyn.mk_AQ tag_a_expression_fmap_emp_term) | 361 tag_a_expression_list2absyn vs rvm ((tag,exp1)::l) = 362 let 363 val tag_term = string2holfoot_tag tag; 364 val (rvm', exp_absyn) = holfoot_expression2absyn vs rvm exp1; 365 val a = Absyn.mk_pair (Absyn.mk_AQ tag_term, exp_absyn) 366 val (rvm'', rest) = tag_a_expression_list2absyn vs rvm' l; 367 in 368 (rvm'', Absyn.list_mk_app (Absyn.mk_AQ tag_a_expression_fmap_update_term, [rest, a])) 369 end; 370 371 372val genpredMap = ref (Redblackmap.mkDict String.compare) 373fun add_genpred (name:string, argL:Parsetree.a_genpredargType list, mk:Absyn.absyn list -> Absyn.absyn) = 374let 375 val map = (!genpredMap); 376 val oldEntry = Redblackmap.find (map, name) handle Redblackmap.NotFound => []; 377 val newEntry = (length argL, argL, mk)::oldEntry; 378 val map = Redblackmap.insert (map, name, newEntry); 379 val _ = genpredMap := map; 380in 381 () 382end; 383 384fun reset_genpreds () = 385let 386 val _ = genpredMap := (Redblackmap.mkDict String.compare); 387in 388 () 389end; 390 391 392fun lookup_genpredL name len = 393let 394 val l = Redblackmap.find ((!genpredMap), name); 395 val l' = filter (fn (len', _, _) => (len = len')) l; 396in 397 List.map (fn (_, argL, mk) => (argL, mk)) l' 398end handle Redblackmap.NotFound => []; 399 400 401local 402 exception arg_exception; 403 404 fun arg2absyn vs (os_opt, cs_opt) Aspred_arg_ty_tag (Aspred_arg_exp (Aexp_ident arg)) = 405 (os_opt, cs_opt, SOME (Absyn.mk_AQ (string2holfoot_tag arg))) 406 | arg2absyn vs (os_opt, cs_opt) Aspred_arg_ty_exp (Aspred_arg_exp arg_exp) = 407 let 408 val (os_opt, exp) = holfoot_expression2absyn vs os_opt arg_exp 409 in 410 (os_opt, cs_opt, SOME exp) 411 end 412 | arg2absyn vs (os_opt, cs_opt) Aspred_arg_ty_hol (Aspred_arg_exp (Aexp_hol arg)) = 413 let 414 val ((os_opt, cs_opt), hol) = HOL_Absyn_old_vars vs (os_opt, cs_opt) arg; 415 in 416 (os_opt, cs_opt, SOME hol) 417 end 418 | arg2absyn vs (os_opt, cs_opt) Aspred_arg_ty_hol (Aspred_arg_exp (Aexp_ident arg)) = 419 arg2absyn vs (os_opt, cs_opt) Aspred_arg_ty_hol (Aspred_arg_exp (Aexp_hol arg)) 420 | arg2absyn vs (os_opt, cs_opt) (Aspred_arg_ty_list Aspred_arg_ty_tag) (Aspred_arg_string_list argL) = 421 let 422 val tag_t = listSyntax.mk_list ( 423 (map string2holfoot_tag argL), Type `:holfoot_tag`); 424 in 425 (os_opt, cs_opt, SOME (Absyn.mk_AQ tag_t)) 426 end 427 | arg2absyn vs (os_opt, cs_opt) Aspred_arg_ty_comma Aspred_arg_comma = 428 (os_opt, cs_opt, NONE) 429 | arg2absyn vs (os_opt, cs_opt) Aspred_arg_ty_colon Aspred_arg_colon = 430 (os_opt, cs_opt, NONE) 431 | arg2absyn vs (os_opt, cs_opt) Aspred_arg_ty_semi Aspred_arg_semi = 432 (os_opt, cs_opt, NONE) 433 | arg2absyn _ _ _ _ = raise arg_exception; 434 435 436 fun args2absyn vs (os_opt, cs_opt) [] [] = (os_opt, cs_opt, []) 437 | args2absyn vs (os_opt, cs_opt) (ty::tys) (arg::args) = 438 let 439 val (os_opt, cs_opt, r_opt) = arg2absyn vs (os_opt, cs_opt) ty arg; 440 val (os_opt, cs_opt, rs) = args2absyn vs (os_opt, cs_opt) tys args; 441 442 val rs' = case r_opt of SOME r => r::rs | NONE => rs; 443 in 444 (os_opt, cs_opt, rs') 445 end; 446 447in 448 449fun holfoot_a_genpred2absyn vs (os_opt, cs_opt) name args line = 450 let 451 val candidates = lookup_genpredL name (length args); 452 fun try_canditate (arg_tys, c) = 453 let 454 val (os_opt, cs_opt, absynArgs) = args2absyn vs (os_opt, cs_opt) arg_tys args 455 in 456 ((os_opt, cs_opt), c absynArgs) 457 end handle arg_exception => Feedback.fail () 458 in 459 tryfind try_canditate candidates handle HOL_ERR _ => 460 let 461 val _ = AssembleHolfootParser.print_parse_error ( 462 "Undefined predicate '"^name^"' found in line "^ 463 (Int.toString (line+1))^"!") 464 in 465 ((os_opt, cs_opt), Absyn.mk_typed(Absyn.mk_ident ("!!!ERROR "^name^"!!!"), 466 Pretype.fromType holfoot_a_proposition_ty)) end 467 end; 468end 469 470 471 472 473fun holfoot_a_space_pred2absyn vs (os_opt, cs_opt) (Aspred_empty) = 474 ((os_opt, cs_opt), Absyn.mk_AQ holfoot_stack_true_term) 475| holfoot_a_space_pred2absyn vs (os_opt, cs_opt) (Aspred_genpred (name,args,(_,line))) = 476 holfoot_a_genpred2absyn vs (os_opt, cs_opt) name args line 477| holfoot_a_space_pred2absyn vs (os_opt, cs_opt) (Aspred_boolhol h) = 478 let 479 val ((os_opt, _), ha) = HOL_Absyn_old_vars vs (os_opt, NONE) h; 480 val used_vars = Redblackset.listItems (Redblackset.intersection (collect_ident ha, fst vs)) 481 in 482 if (null used_vars) then 483 ((os_opt, cs_opt), Absyn.mk_app (Absyn.mk_AQ holfoot_bool_proposition_term, ha)) 484 else 485 let 486 val (qha, vLt) = absyn_extract_vars used_vars ha 487 in 488 ((os_opt, cs_opt), Absyn.list_mk_app (Absyn.mk_AQ holfoot_ap_expression_term, [qha, Absyn.mk_AQ vLt])) 489 end 490 end 491| holfoot_a_space_pred2absyn vs (os_opt, cs_opt) (Aspred_hol s) = 492 HOL_Absyn_old_vars vs (os_opt, cs_opt) s 493| holfoot_a_space_pred2absyn vs (os_opt, cs_opt) (Aspred_pointsto (exp, pl)) = 494 let 495 val (os_opt, a1) = holfoot_expression2absyn vs os_opt exp; 496 val (os_opt, a2) = tag_a_expression_list2absyn vs os_opt pl; 497 in 498 ((os_opt, cs_opt), Absyn.list_mk_app(Absyn.mk_AQ holfoot_ap_points_to_term, [a1, a2])) 499 end; 500 501 502 503fun invariant2a_proposition NONE = 504 Aprop_spred Aspred_empty 505 | invariant2a_proposition (SOME p) = p 506 507 508val holfoot_map_absyn = Absyn ([QUOTE 509 "var_res_map DISJOINT_FMAP_UNION"]) 510 511fun holfoot_a_proposition2absyn_context vs (os_opt,cs_opt) (Aprop_infix (opString, exp1, exp2)) = 512 let 513 val op_term = if (opString = "<") then holfoot_ap_lt_term else 514 if (opString = "<=") then holfoot_ap_le_term else 515 if (opString = ">") then holfoot_ap_gt_term else 516 if (opString = ">=") then holfoot_ap_ge_term else 517 if (opString = "==") then holfoot_ap_equal_term else 518 if (opString = "!=") then holfoot_ap_unequal_term else 519 Raise (holfoot_unsupported_feature_exn ("Aexp_infix "^opString)) 520 val (os_opt, t1) = holfoot_expression2absyn vs os_opt exp1; 521 val (os_opt, t2) = holfoot_expression2absyn vs os_opt exp2; 522 in 523 ((os_opt,cs_opt), Absyn.list_mk_app (Absyn.mk_AQ op_term, [t1, t2])) 524 end 525| holfoot_a_proposition2absyn_context vs (os_opt,cs_opt) (Aprop_false) = 526 ((os_opt,cs_opt), Absyn.mk_AQ holfoot_ap_false_term) 527| holfoot_a_proposition2absyn_context vs (os_opt,cs_opt) (Aprop_ifthenelse (Aprop_infix (opString,exp1,exp2),ap1,ap2)) = 528 let 529 val (ap1,ap2) = if opString = "==" then (ap1,ap2) else 530 if opString = "!=" then (ap2,ap1) else 531 Raise (holfoot_unsupported_feature_exn "Currently only equality checks are allowed as conditions in propositions") 532 533 val (os_opt, exp1) = holfoot_expression2absyn vs os_opt exp1; 534 val (os_opt, exp2) = holfoot_expression2absyn vs os_opt exp2; 535 val ((os_opt,cs_opt), prop1) = holfoot_a_proposition2absyn_context vs (os_opt,cs_opt) ap1; 536 val ((os_opt,cs_opt), prop2) = holfoot_a_proposition2absyn_context vs (os_opt,cs_opt) ap2; 537 in 538 ((os_opt,cs_opt), Absyn.list_mk_app (Absyn.mk_AQ holfoot_ap_eq_cond_term, [exp1, exp2, prop1, prop2])) 539 end 540| holfoot_a_proposition2absyn_context vs (os_opt,cs_opt) (Aprop_ifthenelse _) = 541 Raise (holfoot_unsupported_feature_exn "Currently only equality checks are allowed as conditions in propositions") 542| holfoot_a_proposition2absyn_context vs (os_opt,cs_opt) (Aprop_star (ap1, ap2)) = 543 let 544 val ((os_opt,cs_opt), prop1) = holfoot_a_proposition2absyn_context vs (os_opt,cs_opt) ap1; 545 val ((os_opt,cs_opt), prop2) = holfoot_a_proposition2absyn_context vs (os_opt,cs_opt) ap2; 546 in 547 ((os_opt,cs_opt), Absyn.list_mk_app (Absyn.mk_AQ holfoot_ap_star_term, [prop1, prop2])) 548 end 549| holfoot_a_proposition2absyn_context vs (os_opt,cs_opt) (Aprop_map (vL, ap, l)) = 550 let 551 val vs2 = (fst vs, Redblackset.addList (snd vs, vL)) 552 val ((os_opt,cs_opt), ap_a) = holfoot_a_proposition2absyn_context vs2 (os_opt,cs_opt) ap; 553 val pair_vs = end_itlist (fn v1 => fn v2 => Absyn.VPAIR (locn.Loc_None, v1, v2)) 554 (map (fn v => Absyn.VIDENT (locn.Loc_None, v)) vL) 555 val ap_la = Absyn.mk_lam (pair_vs,ap_a) 556 val l_a = HOL_Absyn l; 557 in 558 ((os_opt,cs_opt), Absyn.list_mk_app (holfoot_map_absyn,[ap_la, l_a])) 559 end 560| holfoot_a_proposition2absyn_context vs (os_opt,cs_opt) (Aprop_spred sp) = 561 holfoot_a_space_pred2absyn vs (os_opt,cs_opt) sp; 562 563 564exception NothingToDo; 565fun add_var_equations m a = 566let 567 val L = Redblackmap.listItems m; 568 val _ = if null L then raise NothingToDo else (); 569 fun mk_old_eq (hv, v) = 570 list_mk_comb (holfoot_ap_equal_term, [ 571 mk_comb(holfoot_exp_var_term, string2holfoot_var hv), 572 mk_comb(holfoot_exp_const_term, v)]) 573 val eqL = List.map mk_old_eq L 574 val eq_star = end_itlist (fn t => fn ts => 575 list_mk_comb (holfoot_ap_star_term, [t, ts])) eqL; 576 577 val a' = Absyn.list_mk_app (Absyn.mk_AQ holfoot_ap_star_term, 578 [Absyn.mk_AQ eq_star, a]) 579in 580 a' 581end handle NothingToDo => a; 582 583 584fun holfoot_a_proposition2absyn vs os_opt x = 585let 586 val ((os_opt,cs_opt), a1) = holfoot_a_proposition2absyn_context vs 587 (os_opt, SOME (Redblackmap.mkDict String.compare)) x; 588 589 val a2 = if isSome cs_opt then add_var_equations (valOf cs_opt) a1 else a1; 590 591 val (s, a3) = remove_qv a2 592 val cs_opt = SOME (Redblackmap.mkDict String.compare) 593 val s' = if not (isSome cs_opt) then s else 594 let 595 val vL = List.map (fst o dest_var o snd) (Redblackmap.listItems (valOf cs_opt)) 596 in 597 Redblackset.addList (s, vL) 598 end 599 val ex_vars = Redblackset.listItems s'; 600 601 val a4 = foldr (fn (v,a) => 602 let 603 val a_lam = Absyn.mk_lam (Absyn.VIDENT (locn.Loc_None, v), a); 604 val a' = Absyn.mk_app (Absyn.mk_ident "asl_exists", a_lam); 605 in a' end) a3 ex_vars 606in 607 (os_opt, a4) 608end; 609 610 611fun mk_holfoot_prop_input_absyn wp rp ap = 612 let 613 val rp = Redblackset.difference (rp, wp); 614 615 val rL = map string2holfoot_var (Redblackset.listItems rp); 616 val wL = map string2holfoot_var (Redblackset.listItems wp); 617 val dL = append rL wL 618 619 val da = mk_list(map Absyn.mk_AQ dL); 620 val rp_term = pred_setSyntax.prim_mk_set (rL, Type `:holfoot_var`); 621 val wp_term = pred_setSyntax.prim_mk_set (wL, Type `:holfoot_var`); 622 val wp_rp_pair_term = pairLib.mk_pair (wp_term, rp_term); 623 in 624 if length dL < 2 then 625 Absyn.list_mk_app (Absyn.mk_AQ holfoot_prop_input_ap_term, [Absyn.mk_AQ wp_rp_pair_term, ap]) 626 else 627 Absyn.list_mk_app (Absyn.mk_AQ holfoot_prop_input_ap_distinct_term, [Absyn.mk_AQ wp_rp_pair_term, da, ap]) 628 end; 629 630fun mk_holfoot_prop_input wp rp t = 631 absyn2term (mk_holfoot_prop_input_absyn wp rp (Absyn.mk_AQ t)); 632 633 634fun holfoot_fcall_get_read_write_var_sets funL (funname:string) args = 635let 636 val (pL, rpe, wpe) = assoc funname funL handle HOL_ERR _ => Feedback.failwith ( 637 "Unknown function '"^funname^"'") 638 val wL = map fst (filter (fn (_, do_write) => do_write) (zip args pL)); 639in 640 (rpe:string list, (wpe@wL):string list) 641end; 642 643 644fun holfoot_fcall2absyn_internal funL vs (name, (rp,vp)) = 645let 646 val name_term = stringLib.fromMLstring name; 647 648 val var_list = map string2holfoot_var rp; 649 val rp_term = listSyntax.mk_list (var_list, Type `:holfoot_var`); 650 651 val vp_a = mk_list (map (fn t => snd (holfoot_expression2absyn vs NONE t)) vp); 652 653 val arg_a = Absyn.mk_pair (Absyn.mk_AQ rp_term, vp_a); 654 val _ = ((assoc name funL);()) handle HOL_ERR _ => 655 let 656 val _ = AssembleHolfootParser.print_parse_error ( 657 "Call of undeclared function '"^name^"' found!"); 658 in 659 Feedback.fail() 660 end; 661 662 val (_,wL) = holfoot_fcall_get_read_write_var_sets funL name rp; 663 val funcalls = [(name, rp)]; 664in 665 (name_term, arg_a, wL, funcalls) 666end; 667 668 669fun holfoot_fcall2absyn funL vs (name, (rp, vp)) = 670let 671 val (name_term, arg_a, wL, funcalls) = 672 holfoot_fcall2absyn_internal funL vs (name, (rp,vp)); 673in 674 (Absyn.list_mk_app(Absyn.mk_AQ holfoot_prog_procedure_call_term, [ 675 Absyn.mk_AQ name_term, arg_a]), wL, funcalls) 676end; 677 678 679fun holfoot_parallel_fcall2absyn funL vs (name1, (rp1, vp1), name2, (rp2,vp2)) = 680let 681 val (name1_term, arg1_a, wL1, funcalls1) = 682 holfoot_fcall2absyn_internal funL vs (name1, (rp1,vp1)); 683 684 val (name2_term, arg2_a, wL2, funcalls2) = 685 holfoot_fcall2absyn_internal funL vs (name2, (rp2,vp2)); 686in 687 (Absyn.list_mk_app(Absyn.mk_AQ holfoot_prog_parallel_procedure_call_term, [ 688 Absyn.mk_AQ name1_term, arg1_a,Absyn.mk_AQ name2_term, arg2_a]), 689 wL1@wL2, funcalls1@funcalls2) 690end; 691 692 693 694val unit_var_term = mk_var("uv", Type `:unit`); 695 696fun mk_list_pabs l = 697 let 698 val pairTerm = if null l then unit_var_term else 699 (pairLib.list_mk_pair l); 700 in 701 fn t => pairLib.mk_pabs (pairTerm,t) 702 end; 703 704fun mk_list_plam l = 705 let 706 val pair_vs = if null l then Absyn.VAQ (locn.Loc_None, unit_var_term) else 707 end_itlist (fn v1 => fn v2 => Absyn.VPAIR (locn.Loc_None, v1, v2)) 708 (map (fn v => Absyn.VAQ (locn.Loc_None, v)) l) 709 in 710 fn a => Absyn.mk_lam (pair_vs,a) 711 end; 712 713 714fun decode_rwOpt rwOpt = if isSome rwOpt then 715 (let val (force, wL, rL) = valOf rwOpt in 716 (force, wL, rL) end) else 717 (false, [], []); 718 719fun find_used_holvars res_varL ts t = 720 case (dest_term t) of 721 VAR (_, ty) => ts 722 | CONST _ => ts 723 | LAMB (t1, t2) => 724 let 725 val emp_s = Redblackset.empty String.compare; 726 val ts1 = find_used_holvars res_varL emp_s t1 727 val ts2 = find_used_holvars res_varL emp_s t2 728 val ts12 = Redblackset.difference (ts2, ts1); 729 in 730 Redblackset.union (ts, ts12) 731 end 732 | COMB (t1, t2) => if (is_holfoot_var t) then Redblackset.add (ts, holfoot_var2string t) else 733 if (is_holfoot_prog_with_resource t) then 734 let 735 val (res_nt, p, b) = dest_holfoot_prog_with_resource t; 736 val tp = find_used_holvars res_varL (Redblackset.empty String.compare) p; 737 val tpb = find_used_holvars res_varL tp b; 738 739 val res_n = stringLib.fromHOLstring res_nt; 740 val res_vars = assoc res_n res_varL; 741 val tpbr = Redblackset.difference (tpb, string_list2set res_vars); 742 in 743 Redblackset.union (ts, tpbr) 744 end else 745 let 746 val ts' = find_used_holvars res_varL ts t1; 747 val ts'' = find_used_holvars res_varL ts' t2; 748 in 749 ts'' 750 end 751 752 753fun get_read_write_var_set res_varL rwOpt wL aL = 754let 755 val (force_user_wr, wL1, rL1) = decode_rwOpt rwOpt; 756 757 val (wL2, rL2) = if force_user_wr then (wL1, rL1) else 758 let 759 val t = absyn2term (Absyn.list_mk_pair aL); 760 val rs = find_used_holvars res_varL (Redblackset.empty String.compare) t; 761 val rL3 = Redblackset.listItems rs; 762 in 763 (wL1 @ wL, rL1@rL3) 764 end 765 766 val write_var_set = string_list2set wL2; 767 val read_var_set = string_list2set rL2; 768 769 val read_var_set' = Redblackset.difference (read_var_set, write_var_set); 770in 771 (write_var_set, read_var_set') 772end; 773 774 775fun rewrite_old_var os pre_a post_a = 776let 777 val pre_a' = add_var_equations os pre_a; 778in 779 (pre_a', post_a) 780end 781 782 783fun global_vars_restrict global_vars = 784 filter (fn v => 785 not (Redblackset.member (global_vars, fst (dest_var v)))); 786 787 788fun free_vars_restrict global_vars t = 789let 790 val fv_list = free_vars t; 791in 792 global_vars_restrict global_vars fv_list 793end 794 795 796(*returns the abstract syntax of the statement as well as set of variables, that need write permissions. 797 The set of variables that are read is figured out independently later. 798 Function calls might add to both sets by either their call-by-reference parameters or by 799 accessing global variables. Therefore, function calls and their call-by-reference parameters 800 are recorded as well *) 801fun holfoot_p_statement2absyn funL resL gv vs (Pstm_assign (v, expr)) = 802 let 803 val var_term = string2holfoot_var v; 804 val (_, exp) = holfoot_expression2absyn vs NONE expr; 805 val comb_a = Absyn.list_mk_app (Absyn.mk_AQ holfoot_prog_assign_term, [Absyn.mk_AQ var_term, exp]); 806 in 807 (comb_a, [v], []) 808 end 809| holfoot_p_statement2absyn funL resL gv vs (Pstm_fldlookup (v, expr, tag)) = 810 let 811 val var_term = string2holfoot_var v; 812 val (_, exp_a) = holfoot_expression2absyn vs NONE expr; 813 val comb_a = Absyn.list_mk_app (Absyn.mk_AQ holfoot_prog_field_lookup_term, 814 [Absyn.mk_AQ var_term, exp_a, Absyn.mk_AQ (string2holfoot_tag tag)]); 815 in 816 (comb_a, [v], []) 817 end 818| holfoot_p_statement2absyn funL resL gv vs (Pstm_fldassign (expr1, tag, expr2)) = 819 let 820 val (_, exp1) = holfoot_expression2absyn vs NONE expr1; 821 val (_, exp2) = holfoot_expression2absyn vs NONE expr2; 822 val comb_a = Absyn.list_mk_app (Absyn.mk_AQ holfoot_prog_field_assign_term, [ 823 exp1, Absyn.mk_AQ (string2holfoot_tag tag), exp2]); 824 in 825 (comb_a, [], []) 826 end 827| holfoot_p_statement2absyn funL resL gv vs (Pstm_new (v, expr, tl)) = 828 let 829 val var_term = string2holfoot_var v; 830 val (_, exp) = holfoot_expression2absyn vs NONE expr; 831 val tl_L = map string2holfoot_tag tl; 832 val tl_t = listSyntax.mk_list (tl_L, holfoot_tag_ty); 833 val comb_a = Absyn.list_mk_app (Absyn.mk_AQ holfoot_prog_new_term, [exp, Absyn.mk_AQ var_term, Absyn.mk_AQ tl_t]); 834 in 835 (comb_a, [v], []) 836 end 837| holfoot_p_statement2absyn funL resL gv vs (Pstm_dispose (expr1, expr2)) = 838 let 839 val (_, exp1) = holfoot_expression2absyn vs NONE expr1; 840 val (_, exp2) = holfoot_expression2absyn vs NONE expr2; 841 val comb_a = Absyn.list_mk_app (Absyn.mk_AQ holfoot_prog_dispose_term, [exp2,exp1]); 842 in 843 (comb_a, [], []) 844 end 845| holfoot_p_statement2absyn funL resL gv vs Pstm_diverge = 846 (Absyn.mk_AQ holfoot_prog_diverge_term, [], []) 847| holfoot_p_statement2absyn funL resL gv vs Pstm_fail = 848 (Absyn.mk_AQ holfoot_prog_fail_term, [], []) 849| holfoot_p_statement2absyn funL resL gv vs (Pstm_block stmL) = 850 let 851 val l0 = map (holfoot_p_statement2absyn funL resL gv vs) stmL; 852 val (aL, wL, fL) = foldr (fn ((a, wL', fL'), (aL, wL, fL)) => 853 (a::aL, wL'@wL, fL'@fL)) ([],[],[]) l0; 854 val comb_a = Absyn.mk_app (Absyn.mk_AQ holfoot_prog_block_term, mk_list aL); 855 in 856 (comb_a, wL, fL) 857 end 858| holfoot_p_statement2absyn funL resL gv vs (Pstm_if (cond, stm1, stm2)) = 859 let 860 val c_a = holfoot_p_condition2absyn vs cond; 861 val (stm1, wL1, fL1) = holfoot_p_statement2absyn funL resL gv vs stm1; 862 val (stm2, wL2, fL2) = holfoot_p_statement2absyn funL resL gv vs stm2; 863 864 val comb_a = Absyn.list_mk_app (Absyn.mk_AQ holfoot_prog_cond_term, 865 [c_a, stm1, stm2]); 866 in 867 (comb_a, wL1@wL2, fL1@fL2) 868 end 869| holfoot_p_statement2absyn funL resL gv vs (Pstm_ndet (stm1, stm2)) = 870 let 871 val (stm1, wL1, fL1) = holfoot_p_statement2absyn funL resL gv vs stm1; 872 val (stm2, wL2, fL2) = holfoot_p_statement2absyn funL resL gv vs stm2; 873 874 val comb_a = Absyn.list_mk_app (Absyn.mk_AQ holfoot_prog_choice_term, 875 [stm1, stm2]); 876 in 877 (comb_a, wL1@wL2, fL1@fL2) 878 end 879| holfoot_p_statement2absyn funL resL gv vs (Pstm_while (unroll, rwOpt, i, cond, stm1)) = 880 let 881 val (use_inv, i_a) = if isSome i then 882 (true, snd (holfoot_a_proposition2absyn vs NONE (valOf i))) 883 else (false, Absyn.mk_AQ holfoot_stack_true_term) 884 885 val (stm1_a, wL, fL) = holfoot_p_statement2absyn funL resL gv vs stm1; 886 val c_a = holfoot_p_condition2absyn vs cond; 887 val while_a = Absyn.list_mk_app (Absyn.mk_AQ holfoot_prog_while_term, [c_a,stm1_a]); 888 889 val (write_var_set, read_var_set) = get_read_write_var_set resL rwOpt wL [i_a, while_a] 890 891 val full_a = if not use_inv then while_a else 892 let 893 val prop_a = mk_holfoot_prop_input_absyn write_var_set read_var_set i_a; 894 val cond_free_var_list = free_vars_restrict gv (absyn2term prop_a); 895 val abs_prop_a = mk_list_plam cond_free_var_list prop_a 896 in 897 Absyn.list_mk_app (Absyn.IDENT (locn.Loc_None, "asl_comment_loop_invariant"), [ 898 abs_prop_a, while_a]) 899 end 900 val unroll_a = if unroll = 0 then full_a else 901 Absyn.list_mk_app (Absyn.IDENT (locn.Loc_None, "asl_comment_loop_unroll"), [ 902 Absyn.mk_AQ (numLib.term_of_int unroll), full_a]) 903 904 in 905 (unroll_a, wL, fL) 906 end 907| holfoot_p_statement2absyn funL resL gv vs (Pstm_block_spec (loop, unroll, rwOpt, pre, stm1, post)) = 908 let 909 val (_, pre_a) = holfoot_a_proposition2absyn vs NONE pre; 910 val (SOME os, post_a) = holfoot_a_proposition2absyn vs (SOME (Redblackmap.mkDict String.compare)) post; 911 val (pre_a, post_a) = rewrite_old_var os pre_a post_a; 912 val (force_user_wr, write_var_set_user, read_var_set_user) = decode_rwOpt rwOpt; 913 914 val (stm1_a, wL, fL) = holfoot_p_statement2absyn funL resL gv vs stm1; 915 916 val (write_var_set, read_var_set) = get_read_write_var_set resL rwOpt wL [ 917 pre_a, post_a, stm1_a] 918 919 val (pre_a2, post_a2) = 920 let 921 val pre_a3 = mk_holfoot_prop_input_absyn write_var_set read_var_set pre_a 922 val post_a3 = mk_holfoot_prop_input_absyn write_var_set read_var_set post_a 923 val cond_free_var_list = global_vars_restrict gv ( 924 HOLset.listItems (FVL [absyn2term pre_a3, absyn2term post_a3] empty_tmset)); 925 val abs_pre_a = mk_list_plam cond_free_var_list pre_a3 926 val abs_post_a = mk_list_plam cond_free_var_list post_a3 927 in 928 (abs_pre_a, abs_post_a) 929 end 930 val stm1_a = if not loop then stm1_a else 931 let 932 fun isPstm_block (Pstm_block _) = true 933 | isPstm_block _ = false; 934 val stm1_a' = if isPstm_block stm1 then stm1_a else 935 (Absyn.mk_app (Absyn.mk_AQ holfoot_prog_block_term, mk_list [stm1_a])); 936 in 937 stm1_a' 938 end; 939 val spec_a = Absyn.list_mk_app ( 940 Absyn.IDENT (locn.Loc_None, if loop then "asl_comment_loop_spec" else 941 "asl_comment_block_spec"), 942 [Absyn.mk_pair (pre_a2, post_a2), stm1_a]); 943 val unroll_a = if unroll = 0 then spec_a else 944 Absyn.list_mk_app (Absyn.IDENT (locn.Loc_None, "asl_comment_loop_unroll"), [ 945 Absyn.mk_AQ (numLib.term_of_int unroll), spec_a]) 946 in 947 (unroll_a, wL, fL) 948 end 949| holfoot_p_statement2absyn funL resL gv vs (Pstm_withres (res, cond, stm1)) = 950 let 951 val c_a = holfoot_p_condition2absyn vs cond; 952 val (stm1_a,wL,fL) = holfoot_p_statement2absyn funL resL gv vs stm1; 953 val res_term = stringLib.fromMLstring res; 954 val res_varL = assoc res resL handle HOL_ERR _ => 955 let 956 val _ = AssembleHolfootParser.print_parse_error ( 957 "Undeclared resource '"^res^"' used!"); 958 in 959 Feedback.fail() 960 end; 961 val wL' = filter (fn v => not (mem v res_varL)) wL; 962 val comb_a = Absyn.list_mk_app (Absyn.mk_AQ holfoot_prog_with_resource_term, [ 963 Absyn.mk_AQ res_term, c_a, stm1_a]); 964 in 965 (comb_a, wL', fL) 966 end 967| holfoot_p_statement2absyn funL resL gv vs (Pstm_assert p) = 968 let 969 val (_, p_a) = holfoot_a_proposition2absyn vs NONE p; 970 val abs_p_a = 971 let 972 val cond_free_var_list = global_vars_restrict gv ( 973 HOLset.listItems (FVL [absyn2term p_a] empty_tmset)); 974 val abs_p_a = mk_list_plam cond_free_var_list p_a 975 in 976 abs_p_a 977 end 978 val comb_a = Absyn.mk_app ( 979 Absyn.IDENT (locn.Loc_None, "asl_comment_assert"), abs_p_a); 980 in 981 (comb_a, [], []) 982 end 983| holfoot_p_statement2absyn funL resL gv vs (Pstm_fcall(name,args)) = 984 holfoot_fcall2absyn funL vs (name, args) 985| holfoot_p_statement2absyn funL resL gv vs (Pstm_parallel_fcall(name1,args1,name2,args2)) = 986 holfoot_parallel_fcall2absyn funL vs (name1, args1, name2, args2); 987 988 989 990(* 991val dummy_fundecl = 992Pfundecl("proc", ([], ["x", "y"]), 993 SOME(Aprop_spred(Aspred_pointsto(Aexp_ident "x", []))), 994 [], 995 [Pstm_fldassign(Pexp_ident "x", "tl", Pexp_ident "y")], 996 SOME(Aprop_spred(Aspred_pointsto(Aexp_ident "x", 997 [("tl", 998 Aexp_ident "y")])))) 999 1000 1001fun destPfundecl (Pfundecl(funname, (ref_args, val_args), preCond, localV, 1002 fun_body, postCond)) = 1003 (funname, (ref_args, val_args), preCond, localV, 1004 fun_body, postCond); 1005 1006val (funname, (ref_args, val_args), preCondOpt, localV, 1007 fun_body, postCondOpt) = destPfundecl dummy_fundecl; 1008 1009val var = "y"; 1010val term = fun_body_term; 1011*) 1012 1013 1014 1015 1016 1017 1018 1019(* 1020 fun dest_Presource (Presource(resname, varL, invariant)) = 1021 (resname, varL, invariant); 1022 1023 1024 val (resname, varL, invariant) = dest_Presource ((el 2 (program_item_decl))); 1025 1026*) 1027 1028 1029fun Presource2hol vs (Presource(resname, varL, invariant)) = 1030let 1031 val write_varL = map string2holfoot_var varL; 1032 val (_, i_a) = holfoot_a_proposition2absyn vs NONE invariant; 1033in 1034 (resname, (absyn2term i_a, write_varL)) 1035end | 1036 Presource2hol _ _ = Raise (holfoot_unsupported_feature_exn ("-")); 1037 1038 1039 1040(* 1041 fun dest_Pfundecl (Pfundecl(funname, (ref_args, val_args), preCondOpt, localV, 1042 fun_body, postCondOpt)) = (funname, (ref_args, val_args), preCondOpt, localV, 1043 fun_body, postCondOpt); 1044 1045 1046 val (funname, (ref_args, val_args), preCondOpt, localV, 1047 fun_body, postCondOpt) = dest_Pfundecl ((el 2 (program_item_decl))); 1048 1049 val resL = resource_parseL 1050 val resL = [] 1051 val funL = [] 1052*) 1053 1054fun extend_set_if_necessary b (s1, s2) = 1055 let 1056 val s' = Redblackset.difference (s2, s1); 1057 in 1058 if Redblackset.isEmpty s' then (s1, b) else 1059 (Redblackset.union (s1, s'), true) 1060 end; 1061 1062 1063fun Pfundecl_preprocess resL global_vars (funL, vs, 1064 Pfundecl(assume_opt, funname, (ref_args, val_args), rwOpt, preCondOpt, localV, 1065 fun_body, postCondOpt)) = 1066let 1067 val (fun_body_a, wL, funcalls) = 1068 holfoot_p_statement2absyn funL resL global_vars vs (Pstm_block fun_body) 1069 1070 val vs_na = (List.foldl (fn (v,vs) => Redblackset.delete (vs, v) handle NotFound => vs) (fst vs) val_args, snd vs); 1071 val (_, pre_a) = holfoot_a_proposition2absyn vs_na NONE (invariant2a_proposition preCondOpt); 1072 val (SOME os, post_a) = holfoot_a_proposition2absyn vs_na (SOME (Redblackmap.mkDict String.compare)) 1073 (invariant2a_proposition postCondOpt); 1074 val (pre_a, post_a) = rewrite_old_var os pre_a post_a; 1075 1076 val aL_t = absyn2term (Absyn.list_mk_pair [fun_body_a, pre_a, post_a]); 1077 val (ws, rs) = get_read_write_var_set resL rwOpt wL [Absyn.mk_AQ aL_t]; 1078 val vs' = Redblackset.union (ws, rs); 1079 val local_vars = val_args@localV; 1080 val ws' = Redblackset.difference (ws, string_list2set local_vars) 1081 val rs' = Redblackset.difference (rs, string_list2set local_vars) 1082 1083 val (vs_vars2, changed) = extend_set_if_necessary false (fst vs, vs'); 1084 val vs2 = (vs_vars2, snd vs); 1085 val (pL, rpe, wpe) = assoc funname funL handle HOL_ERR _ => Feedback.failwith ( 1086 "Unknown function '"^funname^"'") 1087 val pL2 = map (fn s => Redblackset.member (ws', s)) ref_args; 1088 val changed = changed orelse not (pL2 = pL); 1089 1090 val (rps2, changed) = extend_set_if_necessary changed 1091 (string_list2set rpe, Redblackset.difference (rs', string_list2set ref_args)) 1092 val (wps2, changed) = extend_set_if_necessary changed 1093 (string_list2set wpe, Redblackset.difference (ws', string_list2set ref_args)) 1094 val rpe2 = Redblackset.listItems rps2; 1095 val wpe2 = Redblackset.listItems wps2; 1096in 1097 (changed, funname, pre_a, fun_body_a, post_a, ws', rs', vs2, pL2, rpe2, wpe2) 1098end; 1099 1100fun Pfundecl2hol_final (funname, assume_opt, ref_args, val_args, localV, 1101 global_vars, pre_t, fun_body_t, post_t, ws, rs) = 1102 let 1103 val fun_body_local_var_term = foldr holfoot_mk_local_var fun_body_t localV; 1104 1105 val used_vars = ref (free_vars_restrict global_vars fun_body_local_var_term); 1106 fun mk_new_var x = let 1107 val v = variant (!used_vars) (mk_var x); 1108 val _ = used_vars := v::(!used_vars); 1109 in v end; 1110 val arg_ref_term = mk_new_var ("arg_refL", Type `:holfoot_var list`); 1111 val arg_val_term = mk_new_var ("arg_valL", Type `:num list`); 1112 val arg_valL = mk_el_list (length val_args) arg_val_term; 1113 1114 val fun_body_val_args_term = foldr holfoot_mk_call_by_value_arg fun_body_local_var_term (zip val_args arg_valL); 1115 1116 val arg_refL = mk_el_list (length ref_args) arg_ref_term; 1117 val arg_ref_varL = map string2holfoot_var ref_args; 1118 val arg_ref_subst = map (fn (vt, s) => (vt |-> s)) (zip arg_ref_varL arg_refL) 1119 val fun_body_final_term = subst arg_ref_subst fun_body_val_args_term; 1120 val fun_term = pairLib.mk_pabs (pairLib.mk_pair(arg_ref_term, arg_val_term), fun_body_final_term); 1121 1122 val arg_val_varL = map (fn s => mk_comb (holfoot_exp_var_term, string2holfoot_var s)) val_args; 1123 val arg_val_expL = map (fn c => mk_comb (holfoot_exp_const_term, c)) arg_valL; 1124 val arg_val_subst1 = map (fn (vt, s) => (vt |-> s)) (zip arg_val_varL arg_val_expL); 1125 1126 val arg_val_numL = map (fn s => mk_var (s, numLib.num)) val_args; 1127 val arg_val_subst2 = map (fn (vt, s) => (vt |-> s)) (zip arg_val_numL arg_valL); 1128 val arg_val_subst = append arg_val_subst1 arg_val_subst2; 1129 1130 val preCond2 = mk_holfoot_prop_input ws rs pre_t; 1131 val postCond2 = mk_holfoot_prop_input ws rs post_t; 1132 1133 val preCond3 = subst (append arg_val_subst arg_ref_subst) preCond2; 1134 val postCond3 = subst (append arg_val_subst arg_ref_subst) postCond2; 1135 1136 1137 val cond_free_var_list = 1138 let 1139 val set1 = HOLset.addList(empty_tmset, free_vars_restrict global_vars preCond3); 1140 val set2 = HOLset.addList(set1, free_vars_restrict global_vars postCond3); 1141 val set3 = HOLset.delete (set2, arg_ref_term) handle HOLset.NotFound => set2; 1142 val set4 = HOLset.delete (set3, arg_val_term) handle HOLset.NotFound => set3; 1143 val set5 = HOLset.delete (set4, fun_body_final_term) handle HOLset.NotFound => set4; 1144 val fv_list = HOLset.listItems set5; 1145 in 1146 fv_list 1147 end; 1148 1149 val ref_arg_names = listSyntax.mk_list (map string_to_label ref_args, markerSyntax.label_ty); 1150 val val_args_const = map (fn s => s ^ "_const") val_args; 1151 val val_arg_names = listSyntax.mk_list (map string_to_label val_args_const, markerSyntax.label_ty); 1152 1153 val wrapped_preCond = list_mk_icomb (asl_procedure_call_preserve_names_wrapper_term, 1154 [ref_arg_names, val_arg_names, 1155 pairLib.mk_pabs (pairLib.mk_pair(arg_ref_term, arg_val_term), preCond3), 1156 pairLib.mk_pair(arg_ref_term, arg_val_term)]); 1157 1158 val abstr_prog = 1159 list_mk_icomb (holfoot_prog_quant_best_local_action_term, [mk_list_pabs cond_free_var_list wrapped_preCond, mk_list_pabs cond_free_var_list postCond3]) 1160 val abstr_prog_val_args_term = pairLib.mk_pabs (pairLib.mk_pair(arg_ref_term, arg_val_term), abstr_prog); 1161 1162 (*access to global variables*) 1163 val global_vars = Redblackset.listItems (Redblackset.difference (Redblackset.union (ws, rs), 1164 string_list2set (ref_args @ val_args @ localV))) 1165in 1166 (assume_opt, funname, fun_term, abstr_prog_val_args_term, global_vars) 1167end; 1168 1169 1170fun Pfundecl_list2hol global_vars res_varL fun_decl_list = 1171let 1172 fun initPfundecl (Pfundecl(assume_opt, funname, (ref_args, val_args), rwOpt, preCondOpt, localV, 1173 fun_body, postCondOpt)) = 1174 (funname, ((map (K false) ref_args), []:string list, []:string list)) 1175 val init_funL = map initPfundecl fun_decl_list; 1176 val emp_s = Redblackset.empty String.compare 1177 val init = map (fn p => (init_funL, (emp_s,emp_s), p)) fun_decl_list 1178 1179 fun internal l = 1180 let 1181 val l' = map (Pfundecl_preprocess res_varL global_vars) l; 1182 val changed = exists (#1) l'; 1183 in 1184 if changed then 1185 let 1186 fun iter_funL (changed, funname, pre_a, fun_body_a, post_a, ws', rs', vs2, pL2, rpe2, wpe2) = 1187 (funname, (pL2, rpe2, wpe2)) 1188 val funL' = map iter_funL l'; 1189 fun iter_fin (p, (changed, funname, pre_a, fun_body_a, post_a, ws', rs', vs2, pL2, rpe2, wpe2)) = 1190 (funL', vs2, p) 1191 val l'' = map iter_fin (zip fun_decl_list l') 1192 in 1193 internal l'' 1194 end 1195 else 1196 let 1197 fun fin (changed, funname, pre_a, fun_body_a, post_a, ws', rs', vs2, pL2, rpe2, wpe2) = 1198 (funname, pre_a, fun_body_a, post_a, ws', rs') 1199 in 1200 map fin l' 1201 end 1202 end; 1203 1204 fun extract (Pfundecl(assume_opt, funname, (ref_args, val_args), rwOpt, preCondOpt, localV, 1205 fun_body, postCondOpt), (funname2, pre_a, fun_body_a, post_a, ws, rs)) = 1206 let 1207 val tp = absyn2term (Absyn.list_mk_pair [pre_a, fun_body_a, post_a]); 1208 val tL = pairSyntax.strip_pair tp; 1209 val pre_t = el 1 tL 1210 val fun_body_t = el 2 tL 1211 val post_t = el 3 tL 1212 in 1213 (funname, assume_opt, ref_args, val_args, localV, global_vars, 1214 pre_t, fun_body_t, post_t, ws, rs) 1215 end; 1216 1217 val finalL = map extract (zip fun_decl_list (internal init)) 1218 1219in 1220 map Pfundecl2hol_final finalL 1221end; 1222 1223 1224 1225fun add_init_spec init_post_prop (Pfundecl(assume_opt, funname, (ref_args, val_args), rwOpt, preCondOpt, localV, 1226 fun_body, postCondOpt)) = 1227 if (not (funname = "init")) then 1228 Pfundecl(assume_opt, funname, (ref_args, val_args), rwOpt, preCondOpt, localV, 1229 fun_body, postCondOpt) (*unchanged*) 1230 else 1231 let 1232 val _ = if isSome preCondOpt orelse isSome postCondOpt orelse 1233 isSome rwOpt orelse 1234 not (ref_args = []) orelse not (val_args = []) then 1235 raise holfoot_unsupported_feature_exn ("init function must not have parameters or pre- / postconditions") else (); 1236 val preCondOpt' = SOME (Aprop_spred Aspred_empty) 1237 val postCondOpt' = SOME init_post_prop 1238 in 1239 Pfundecl(assume_opt, funname, (ref_args, val_args), rwOpt, preCondOpt', localV, 1240 fun_body, postCondOpt') 1241 end; 1242 1243 1244(* 1245 1246val (funname, (ref_args, write_var_set, read_var_set, local_var_set, 1247 funcalls, done_funcalls), 1248 (fun_body_term, val_args, localV, preCond, postCond)) = 1249 hd fun_decl_parse_read_writeL3; 1250*) 1251 1252 1253 1254fun p_item___is_fun_decl (Pfundecl _) = true | 1255 p_item___is_fun_decl _ = false; 1256 1257 1258fun p_item___is_resource (Presource _) = true | 1259 p_item___is_resource _ = false; 1260 1261(* 1262val examplesDir = Globals.HOLDIR ^ "/examples/separationLogic/src/holfoot/EXAMPLES/"; 1263val file = examplesDir ^ "mem.sf" ; 1264 1265 1266val examplesDir = Globals.HOLDIR ^ "/examples/separationLogic/src/holfoot/EXAMPLES/"; 1267val file = examplesDir ^ "/automatic/entailments.ent" ; 1268 1269val prog2 = parse file 1270val t = parse_holfoot_file file 1271 1272 1273fun dest_Pprogram (Pprogram (ident_decl, program_item_decl)) = 1274 (ident_decl, program_item_decl); 1275 1276val (ident_decl, program_item_decl) = dest_Pprogram prog2; 1277 1278val Pentailments ((comment, p1, p2)::_) = prog2 1279*) 1280 1281fun find_duplicates [] = [] 1282 | find_duplicates (x::xs) = 1283 let 1284 val (xL,xs') = partition (fn y => (x = y)) xs; 1285 val dL = find_duplicates xs'; 1286 in 1287 if null xL then dL else ((hd xL)::dL) 1288 end; 1289 1290 1291fun Pprogram2hol procL_opt (Pprogram (ident_decl, global_decl, program_item_decl)) = 1292 let 1293 (*ignore ident_decl*) 1294 1295 (*parse resources*) 1296 val resource_list = filter p_item___is_resource program_item_decl; 1297 val resource_names = map (fn Presource (name,_,_) => name) resource_list; 1298 val resource_names_dL = find_duplicates resource_names; 1299 val _ = if null resource_names_dL then () else 1300 (AssembleHolfootParser.print_parse_error (String.concat ( 1301 "Multiple resource definition found for:\n":: 1302 (map (fn n => (" - '"^n^"'\n")) resource_names_dL)));Feedback.fail ()); 1303 1304 val emp_s = (Redblackset.empty String.compare); 1305 val resource_parseL = map (Presource2hol (emp_s, emp_s)) resource_list; 1306 val resource_parse_termL = map (fn (name, (prop, vars)) => 1307 let 1308 val name_term = stringLib.fromMLstring name; 1309 val varL = listSyntax.mk_list (vars, Type `:holfoot_var`); 1310 in 1311 pairLib.mk_pair(name_term, pairLib.mk_pair(varL, prop)) 1312 end) resource_parseL 1313 val resource_parseL_term = listSyntax.mk_list (resource_parse_termL, 1314 Type `:string # holfoot_var list # holfoot_a_proposition`); 1315 val resource_term = mk_comb (HOLFOOT_LOCK_ENV_MAP_term, resource_parseL_term); 1316 1317 1318 (*parse procedure specs*) 1319 val fun_decl_list = filter p_item___is_fun_decl program_item_decl; 1320 val fun_names = map (fn Pfundecl (_,name,_,_,_,_,_,_) => name) fun_decl_list; 1321 val fun_names_dL = find_duplicates fun_names; 1322 val _ = if null fun_names_dL then () else 1323 (AssembleHolfootParser.print_parse_error (String.concat ( 1324 "Multiple procedure definition found for:\n":: 1325 (map (fn n => (" - '"^n^"'\n")) fun_names_dL)));Feedback.fail ()); 1326 1327 val res_varL = map (fn Presource (n, vL, _) => (n, vL)) resource_list; 1328 val res_propL = map (fn Presource (_, _, p) => p) resource_list; 1329 val init_post_prop = if null res_propL then Aprop_spred Aspred_empty else 1330 (end_itlist (curry Aprop_star) res_propL) 1331 val fun_decl_list_init = map (add_init_spec init_post_prop) fun_decl_list 1332 val global_vars = string_list2set global_decl; 1333 val fun_decl_parseL = Pfundecl_list2hol global_vars res_varL fun_decl_list_init 1334 1335 fun assume_proc_spec assume_opt proc = 1336 if (not assume_opt) then F else 1337 if (not (isSome procL_opt)) then T else 1338 if (mem proc (valOf procL_opt)) then T else F; 1339 1340 fun mk_pair_terms (assume_opt, s, fun_body, spec, _) = 1341 pairLib.list_mk_pair [assume_proc_spec assume_opt s, stringLib.fromMLstring s, fun_body, spec]; 1342 val fun_decl_parse_pairL = map mk_pair_terms fun_decl_parseL; 1343 1344 val input = listSyntax.mk_list (fun_decl_parse_pairL, type_of (hd fun_decl_parse_pairL)); 1345 1346 1347 (* check for problems with variables protected by locks being used *) 1348 fun check_vars (_, fname, _, _, gvs) (Presource (rname, rvs, _)) = 1349 let 1350 val il = Lib.intersect gvs rvs; 1351 in 1352 if null il orelse (fname = "init") then NONE else SOME (fname, rname, il) 1353 end; 1354 val error_list = map valOf (filter isSome (flatten (map (fn fd => map (check_vars fd) resource_list) fun_decl_parseL))); 1355 val _ = if null error_list then () else 1356 let 1357 fun error_report (fname, rname, vl) = 1358 String.concat ["The function '", fname, "' accesses the variables [", 1359 String.concat (Lib.commafy vl), "] which are protected by resource '", rname, "'!\n"]; 1360 in 1361 (AssembleHolfootParser.print_parse_error (String.concat ( 1362 map error_report error_list));Feedback.fail ()) 1363 end; 1364 in 1365 (list_mk_icomb (HOLFOOT_SPECIFICATION_term, [resource_term, input])) 1366 end; 1367 1368 1369fun mk_entailment (comment, p1, p2) = 1370let 1371 val empty_vs = (Redblackset.empty String.compare, Redblackset.empty String.compare); 1372 val (_, a1) = holfoot_a_proposition2absyn empty_vs NONE p1 1373 val (_, a2) = holfoot_a_proposition2absyn empty_vs NONE p2 1374 val (write_var_set, read_var_set) = get_read_write_var_set [] NONE [] [a1, a2] 1375 val varL = Redblackset.listItems (Redblackset.union (write_var_set, read_var_set)) 1376 val var_tL = map string2holfoot_var varL 1377 val r_bag = bagSyntax.mk_bag (var_tL, holfoot_var_ty); 1378 val w_bag = bagSyntax.mk_bag ([], holfoot_var_ty); 1379 val bag_t = pairSyntax.mk_pair (w_bag, r_bag) 1380 1381 val sr_t = pairSyntax.mk_pair (F, optionSyntax.mk_some 1382 (listSyntax.mk_list ([string_to_label comment], markerSyntax.label_ty))) 1383 1384 val a12_t = absyn2term (Absyn.mk_pair (a1, a2)); 1385 val b1 = bagSyntax.mk_bag (strip_asl_star (rand (rator a12_t)), 1386 holfoot_a_proposition_ty) 1387 val b2 = bagSyntax.mk_bag (strip_asl_star (rand a12_t), holfoot_a_proposition_ty); 1388 1389 val t0 = list_mk_comb (HOLFOOT_VAR_RES_FRAME_SPLIT_term, [sr_t, bag_t]); 1390 val t1 = mk_comb (t0, inst [alpha |-> holfoot_var_ty] bagSyntax.EMPTY_BAG_tm) 1391 val t2 = mk_comb (t1, inst [alpha |-> holfoot_a_proposition_ty] bagSyntax.EMPTY_BAG_tm) 1392 val t3 = list_mk_comb (t2, [b1,b2, HOLFOOT_VAR_RES_FRAME_SPLIT___EMP_PRED_term]); 1393in 1394 t3 1395end; 1396 1397 1398fun Pentailments2hol res_opt (Pentailments eL) = 1399 let 1400 val eL' = if isSome (res_opt) then 1401 filter (fn (c, p1, p2) => mem c (valOf res_opt)) eL else eL 1402 val tL = List.map mk_entailment eL' 1403 in 1404 (boolSyntax.list_mk_conj tL) 1405 end; 1406 1407fun Ptop2hol res_opt (Pentailments x) = 1408 Pentailments2hol res_opt (Pentailments x) 1409 | Ptop2hol res_opt (Pprogram x) = 1410 Pprogram2hol res_opt (Pprogram x); 1411 1412val parse_holfoot_file = (Ptop2hol NONE) o parse; 1413fun parse_holfoot_file_restrict procL = (Ptop2hol (SOME procL)) o parse; 1414 1415 1416 1417fun print_file_contents file = 1418 let 1419 val is = Portable.open_in file 1420 val _ = print ("\nContents of file \""^file^"\":\n\n"); 1421 val _ = print "--------------------------------------------\n"; 1422 val _ = while (not (Portable.end_of_stream is)) do 1423 (print (Portable.input_line is)); 1424 val _ = Portable.close_in is; 1425 val _ = print "--------------------------------------------\n\n"; 1426 in 1427 () 1428 end 1429 1430end 1431