diff options
Diffstat (limited to 'contrib/correctness/pwp.ml')
-rw-r--r-- | contrib/correctness/pwp.ml | 347 |
1 files changed, 0 insertions, 347 deletions
diff --git a/contrib/correctness/pwp.ml b/contrib/correctness/pwp.ml deleted file mode 100644 index f422c5cd..00000000 --- a/contrib/correctness/pwp.ml +++ /dev/null @@ -1,347 +0,0 @@ -(************************************************************************) -(* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *) -(* \VV/ **************************************************************) -(* // * This file is distributed under the terms of the *) -(* * GNU Lesser General Public License Version 2.1 *) -(************************************************************************) - -(* Certification of Imperative Programs / Jean-Christophe Filliātre *) - -(* $Id: pwp.ml 8752 2006-04-27 19:37:33Z herbelin $ *) - -open Util -open Names -open Libnames -open Term -open Termops -open Environ -open Nametab - -open Pmisc -open Ptype -open Past -open Putil -open Penv -open Peffect -open Ptyping -open Prename - -(* In this module: - * - we try to insert more annotations to achieve a greater completeness; - * - we recursively propagate annotations inside programs; - * - we normalize boolean expressions. - * - * The propagation schemas are the following: - * - * 1. (f a1 ... an) -> (f a1 ... an) {Qf} if the ai are functional - * - * 2. (if e1 then e2 else e3) {Q} -> (if e1 then e2 {Q} else e3 {Q}) {Q} - * - * 3. (let x = e1 in e2) {Q} -> (let x = e1 in e2 {Q}) {Q} - *) - -(* force a post-condition *) -let update_post env top ef c = - let i,o = Peffect.get_repr ef in - let al = - List.fold_left - (fun l id -> - if is_mutable_in_env env id then - if is_write ef id then l else (id,at_id id "")::l - else if is_at id then - let (uid,d) = un_at id in - if is_mutable_in_env env uid & d="" then - (id,at_id uid top)::l - else - l - else - l) - [] (global_vars (Global.env()) c) - in - subst_in_constr al c - -let force_post up env top q e = - let (res,ef,p,_) = e.info.kappa in - let q' = - if up then option_map (named_app (update_post env top ef)) q else q - in - let i = { env = e.info.env; kappa = (res,ef,p,q') } in - { desc = e.desc; pre = e.pre; post = q'; loc = e.loc; info = i } - -(* put a post-condition if none is present *) -let post_if_none_up env top q = function - | { post = None } as p -> force_post true env top q p - | p -> p - -let post_if_none env q = function - | { post = None } as p -> force_post false env "" q p - | p -> p - -(* [annotation_candidate p] determines if p is a candidate for a - * post-condition *) - -let annotation_candidate = function - | { desc = If _ | Let _ | LetRef _ ; post = None } -> true - | _ -> false - -(* [extract_pre p] erase the pre-condition of p and returns it *) -let extract_pre pr = - let (v,e,p,q) = pr.info.kappa in - { desc = pr.desc; pre = []; post = pr.post; loc = pr.loc; - info = { env = pr.info.env; kappa = (v,e,[],q) } }, - p - -(* adds some pre-conditions *) -let add_pre p1 pr = - let (v,e,p,q) = pr.info.kappa in - let p' = p1 @ p in - { desc = pr.desc; pre = p'; post = pr.post; loc = pr.loc; - info = { env = pr.info.env; kappa = (v,e,p',q) } } - -(* change the statement *) -let change_desc p d = - { desc = d; pre = p.pre; post = p.post; loc = p.loc; info = p.info } - -let create_bool_post c = - Some { a_value = c; a_name = Name (bool_name()) } - -(* [normalize_boolean b] checks if the boolean expression b (of type bool) is - * annotated, and if it is not the case tries to add the annotation - * (if result then c=true else c=false) if b is an expression c. - *) - -let is_bool = function - | TypePure c -> - (match kind_of_term (strip_outer_cast c) with - | Ind op -> - string_of_id (id_of_global (IndRef op)) = "bool" - | _ -> false) - | _ -> false - -let normalize_boolean ren env b = - let ((res,v),ef,p,q) = b.info.kappa in - Perror.check_no_effect b.loc ef; - if is_bool v then - match q with - | Some _ -> - (* il y a une annotation : on se contente de lui forcer un nom *) - let q = force_bool_name q in - { desc = b.desc; pre = b.pre; post = q; loc = b.loc; - info = { env = b.info.env; kappa = ((res,v),ef,p,q) } } - | None -> begin - (* il n'y a pas d'annotation : on cherche ą en mettre une *) - match b.desc with - Expression c -> - let c' = Term.applist (constant "annot_bool",[c]) in - let ty = type_of_expression ren env c' in - let (_,q') = Hipattern.match_sigma ty in - let q' = Some { a_value = q'; a_name = Name (bool_name()) } in - { desc = Expression c'; - pre = b.pre; post = q'; loc = b.loc; - info = { env = b.info.env; kappa = ((res, v),ef,p,q') } } - | _ -> b - end - else - Perror.should_be_boolean b.loc - -(* [decomp_boolean c] returns the specs R and S of a boolean expression *) - -let decomp_boolean = function - | Some { a_value = q } -> - Reductionops.whd_betaiota (Term.applist (q, [constant "true"])), - Reductionops.whd_betaiota (Term.applist (q, [constant "false"])) - | _ -> invalid_arg "Ptyping.decomp_boolean" - -(* top point of a program *) - -let top_point = function - | PPoint (s,_) as p -> s,p - | p -> let s = label_name() in s,PPoint(s,p) - -let top_point_block = function - | (Label s :: _) as b -> s,b - | b -> let s = label_name() in s,(Label s)::b - -let abstract_unit q = abstract [result_id,constant "unit"] q - -(* [add_decreasing env ren ren' phi r bl] adds the decreasing condition - * phi(ren') r phi(ren) - * to the last assertion of the block [bl], which is created if needed - *) - -let add_decreasing env inv (var,r) lab bl = - let ids = now_vars env var in - let al = List.map (fun id -> (id,at_id id lab)) ids in - let var_lab = subst_in_constr al var in - let dec = Term.applist (r, [var;var_lab]) in - let post = match inv with - None -> anonymous dec - | Some i -> { a_value = conj dec i.a_value; a_name = i.a_name } - in - bl @ [ Assert post ] - -(* [post_last_statement env top q bl] annotates the last statement of the - * sequence bl with q if necessary *) - -let post_last_statement env top q bl = - match List.rev bl with - | Statement e :: rem when annotation_candidate e -> - List.rev ((Statement (post_if_none_up env top q e)) :: rem) - | _ -> bl - -(* [propagate_desc] moves the annotations inside the program - * info is the typing information coming from the outside annotations *) -let rec propagate_desc ren info d = - let env = info.env in - let (_,_,p,q) = info.kappa in - match d with - | If (e1,e2,e3) -> - (* propagation number 2 *) - let e1' = normalize_boolean ren env (propagate ren e1) in - if e2.post = None or e3.post = None then - let top = label_name() in - let ren' = push_date ren top in - PPoint (top, If (e1', - propagate ren' (post_if_none_up env top q e2), - propagate ren' (post_if_none_up env top q e3))) - else - If (e1', propagate ren e2, propagate ren e3) - | Aff (x,e) -> - Aff (x, propagate ren e) - | TabAcc (ch,x,e) -> - TabAcc (ch, x, propagate ren e) - | TabAff (ch,x,({desc=Expression c} as e1),e2) -> - let p = Pmonad.make_pre_access ren env x c in - let e1' = add_pre [(anonymous_pre true p)] e1 in - TabAff (false, x, propagate ren e1', propagate ren e2) - | TabAff (ch,x,e1,e2) -> - TabAff (ch, x, propagate ren e1, propagate ren e2) - | Apply (f,l) -> - Apply (propagate ren f, List.map (propagate_arg ren) l) - | SApp (f,l) -> - let l = - List.map (fun e -> normalize_boolean ren env (propagate ren e)) l - in - SApp (f, l) - | Lam (bl,e) -> - Lam (bl, propagate ren e) - | Seq bl -> - let top,bl = top_point_block bl in - let bl = post_last_statement env top q bl in - Seq (propagate_block ren env bl) - | While (b,inv,var,bl) -> - let b = normalize_boolean ren env (propagate ren b) in - let lab,bl = top_point_block bl in - let bl = add_decreasing env inv var lab bl in - While (b,inv,var,propagate_block ren env bl) - | LetRef (x,e1,e2) -> - let top = label_name() in - let ren' = push_date ren top in - PPoint (top, LetRef (x, propagate ren' e1, - propagate ren' (post_if_none_up env top q e2))) - | Let (x,e1,e2) -> - let top = label_name() in - let ren' = push_date ren top in - PPoint (top, Let (x, propagate ren' e1, - propagate ren' (post_if_none_up env top q e2))) - | LetRec (f,bl,v,var,e) -> - LetRec (f, bl, v, var, propagate ren e) - | PPoint (s,d) -> - PPoint (s, propagate_desc ren info d) - | Debug _ | Variable _ - | Acc _ | Expression _ as d -> d - - -(* [propagate] adds new annotations if possible *) -and propagate ren p = - let env = p.info.env in - let p = match p.desc with - | Apply (f,l) -> - let _,(_,so,ok),(_,_,_,qapp) = effect_app ren env f l in - if ok then - let q = option_map (named_app (real_subst_in_constr so)) qapp in - post_if_none env q p - else - p - | _ -> p - in - let d = propagate_desc ren p.info p.desc in - let p = change_desc p d in - match d with - | Aff (x,e) -> - let e1,p1 = extract_pre e in - change_desc (add_pre p1 p) (Aff (x,e1)) - - | TabAff (check, x, ({ desc = Expression _ } as e1), e2) -> - let e1',p1 = extract_pre e1 in - let e2',p2 = extract_pre e2 in - change_desc (add_pre (p1@p2) p) (TabAff (check,x,e1',e2')) - - | While (b,inv,_,_) -> - let _,s = decomp_boolean b.post in - let s = make_before_after s in - let q = match inv with - None -> Some (anonymous s) - | Some i -> Some { a_value = conj i.a_value s; a_name = i.a_name } - in - let q = option_map (named_app abstract_unit) q in - post_if_none env q p - - | SApp ([Variable id], [e1;e2]) - when id = connective_and or id = connective_or -> - let (_,_,_,q1) = e1.info.kappa - and (_,_,_,q2) = e2.info.kappa in - let (r1,s1) = decomp_boolean q1 - and (r2,s2) = decomp_boolean q2 in - let q = - let conn = if id = connective_and then "spec_and" else "spec_or" in - let c = Term.applist (constant conn, [r1; s1; r2; s2]) in - let c = Reduction.whd_betadeltaiota (Global.env()) c in - create_bool_post c - in - let d = - SApp ([Variable id; - Expression (out_post q1); - Expression (out_post q2)], - [e1; e2] ) - in - post_if_none env q (change_desc p d) - - | SApp ([Variable id], [e1]) when id = connective_not -> - let (_,_,_,q1) = e1.info.kappa in - let (r1,s1) = decomp_boolean q1 in - let q = - let c = Term.applist (constant "spec_not", [r1; s1]) in - let c = Reduction.whd_betadeltaiota (Global.env ()) c in - create_bool_post c - in - let d = SApp ([Variable id; Expression (out_post q1)], [ e1 ]) in - post_if_none env q (change_desc p d) - - | _ -> p - -and propagate_arg ren = function - | Type _ | Refarg _ as a -> a - | Term e -> Term (propagate ren e) - - -and propagate_block ren env = function - | [] -> - [] - | (Statement p) :: (Assert q) :: rem when annotation_candidate p -> - (* TODO: plutot p.post = None ? *) - let q' = - let ((id,v),_,_,_) = p.info.kappa in - let tv = Pmonad.trad_ml_type_v ren env v in - named_app (abstract [id,tv]) q - in - let p' = post_if_none env (Some q') p in - (Statement (propagate ren p')) :: (Assert q) - :: (propagate_block ren env rem) - | (Statement p) :: rem -> - (Statement (propagate ren p)) :: (propagate_block ren env rem) - | (Label s as x) :: rem -> - x :: propagate_block (push_date ren s) env rem - | x :: rem -> - x :: propagate_block ren env rem |