diff options
Diffstat (limited to 'contrib/correctness/ptyping.ml')
-rw-r--r-- | contrib/correctness/ptyping.ml | 600 |
1 files changed, 0 insertions, 600 deletions
diff --git a/contrib/correctness/ptyping.ml b/contrib/correctness/ptyping.ml deleted file mode 100644 index 91c1f293..00000000 --- a/contrib/correctness/ptyping.ml +++ /dev/null @@ -1,600 +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: ptyping.ml 5920 2004-07-16 20:01:26Z herbelin $ *) - -open Pp -open Util -open Names -open Term -open Termops -open Environ -open Constrintern -open Himsg -open Proof_trees -open Topconstr - -open Pmisc -open Putil -open Prename -open Ptype -open Past -open Penv -open Peffect -open Pcicenv - -(* Ce module implante le jugement Gamma |-a e : kappa de la thèse. - * Les annotations passent du type CoqAst.t au type Term.constr ici. - * Les post-conditions sont abstraites par rapport au résultat. *) - -let simplify_type_of env sigma t = - Reductionops.nf_betaiota (Typing.type_of env sigma t) - -let just_reads e = - difference (get_reads e) (get_writes e) - -let type_v_sup loc t1 t2 = - if t1 = t2 then - t1 - else - Perror.if_branches loc - -let typed_var ren env (phi,r) = - let sign = Pcicenv.before_after_sign_of ren env in - let a = simplify_type_of (Global.env_of_context sign) Evd.empty phi in - (phi,r,a) - -(* Application de fonction *) - -let rec convert = function - | (TypePure c1, TypePure c2) -> - Reductionops.is_conv (Global.env ()) Evd.empty c1 c2 - | (Ref v1, Ref v2) -> - convert (v1,v2) - | (Array (s1,v1), Array (s2,v2)) -> - (Reductionops.is_conv (Global.env ()) Evd.empty s1 s2) && (convert (v1,v2)) - | (v1,v2) -> v1 = v2 - -let effect_app ren env f args = - let n = List.length args in - let tf = - let ((_,v),_,_,_) = f.info.kappa in - match v with TypePure c -> v_of_constr c | _ -> v - in - let bl,c = - match tf with - Arrow (bl, c) -> - if List.length bl <> n then Perror.partial_app f.loc; - bl,c - | _ -> Perror.app_of_non_function f.loc - in - let check_type loc v t so = - let v' = type_v_rsubst so v in - if not (convert (v',t)) then Perror.expected_type loc (pp_type_v v') - in - let s,so,ok = - (* s est la substitution des références, so celle des autres arg. - * ok nous dit si les arguments sont sans effet i.e. des expressions *) - List.fold_left - (fun (s,so,ok) (b,a) -> - match b,a with - (id,BindType (Ref _ | Array _ as v)), Refarg id' -> - let ta = type_in_env env id' in - check_type f.loc v ta so; - (id,id')::s, so, ok - | _, Refarg _ -> Perror.should_be_a_variable f.loc - | (id,BindType v), Term t -> - let ((_,ta),_,_,_) = t.info.kappa in - check_type t.loc v ta so; - (match t.desc with - Expression c -> s, (id,c)::so, ok - | _ -> s,so,false) - | (id,BindSet), Type v -> - let c = Pmonad.trad_ml_type_v ren env v in - s, (id,c)::so, ok - | (id,BindSet), Term t -> Perror.expects_a_type id t.loc - | (id,BindType _), Type _ -> Perror.expects_a_term id - | (_,Untyped), _ -> invalid_arg "effects_app") - ([],[],true) - (List.combine bl args) - in - let (id,v),ef,pre,post = type_c_subst s c in - (bl,c), (s,so,ok), ((id,type_v_rsubst so v),ef,pre,post) - -(* Execution of a Coq AST. Returns value and type. - * Also returns its variables *) - -let state_coq_ast sign a = - let env = Global.env_of_context sign in - let j = - reraise_with_loc (constr_loc a) (judgment_of_rawconstr Evd.empty env) a in - let ids = global_vars env j.uj_val in - j.uj_val, j.uj_type, ids - -(* [is_pure p] tests wether the program p is an expression or not. *) - -let type_of_expression ren env c = - let sign = now_sign_of ren env in - simplify_type_of (Global.env_of_context sign) Evd.empty c - -let rec is_pure_type_v = function - TypePure _ -> true - | Arrow (bl,c) -> List.for_all is_pure_arg bl & is_pure_type_c c - | Ref _ | Array _ -> false -and is_pure_arg = function - (_,BindType v) -> is_pure_type_v v - | (_,BindSet) -> true - | (_,Untyped) -> false -and is_pure_type_c = function - (_,v),_,[],None -> is_pure_type_v v - | _ -> false - -let rec is_pure_desc ren env = function - Variable id -> - not (is_in_env env id) or (is_pure_type_v (type_in_env env id)) - | Expression c -> - (c = isevar) or (is_pure_cci (type_of_expression ren env c)) - | Acc _ -> true - | TabAcc (_,_,p) -> is_pure ren env p - | Apply (p,args) -> - is_pure ren env p & List.for_all (is_pure_arg ren env) args - | SApp _ | Aff _ | TabAff _ | Seq _ | While _ | If _ - | Lam _ | LetRef _ | Let _ | LetRec _ -> false - | Debug (_,p) -> is_pure ren env p - | PPoint (_,d) -> is_pure_desc ren env d -and is_pure ren env p = - p.pre = [] & p.post = None & is_pure_desc ren env p.desc -and is_pure_arg ren env = function - Term p -> is_pure ren env p - | Type _ -> true - | Refarg _ -> false - -(* [state_var ren env (phi,r)] returns a tuple (e,(phi',r')) - * where e is the effect of the variant phi and phi',r' the corresponding - * constr of phi and r. - *) - -let state_var ren env (phi,r) = - let sign = Pcicenv.before_after_sign_of ren env in - let phi',_,ids = state_coq_ast sign phi in - let ef = List.fold_left - (fun e id -> - if is_mutable_in_env env id then Peffect.add_read id e else e) - Peffect.bottom ids in - let r',_,_ = state_coq_ast (Global.named_context ()) r in - ef,(phi',r') - -(* [state_pre ren env pl] returns a pair (e,c) where e is the effect of the - * pre-conditions list pl and cl the corresponding constrs not yet abstracted - * over the variables xi (i.e. c NOT [x1]...[xn]c !) - *) - -let state_pre ren env pl = - let state e p = - let sign = Pcicenv.before_sign_of ren env in - let cc,_,ids = state_coq_ast sign p.p_value in - let ef = List.fold_left - (fun e id -> - if is_mutable_in_env env id then - Peffect.add_read id e - else if is_at id then - let uid,_ = un_at id in - if is_mutable_in_env env uid then - Peffect.add_read uid e - else - e - else - e) - e ids - in - ef,{ p_assert = p.p_assert; p_name = p.p_name; p_value = cc } - in - List.fold_left - (fun (e,cl) p -> let ef,c = state e p in (ef,c::cl)) - (Peffect.bottom,[]) pl - -let state_assert ren env a = - let p = pre_of_assert true a in - let e,l = state_pre ren env [p] in - e,assert_of_pre (List.hd l) - -let state_inv ren env = function - None -> Peffect.bottom, None - | Some i -> let e,p = state_assert ren env i in e,Some p - -(* [state_post ren env (id,v,ef) q] returns a pair (e,c) - * where e is the effect of the - * post-condition q and c the corresponding constr not yet abstracted - * over the variables xi, yi and result. - * Moreover the RW variables not appearing in ef have been replaced by - * RO variables, and (id,v) is the result - *) - -let state_post ren env (id,v,ef) = function - None -> Peffect.bottom, None - | Some q -> - let v' = Pmonad.trad_ml_type_v ren env v in - let sign = Pcicenv.before_after_result_sign_of (Some (id,v')) ren env in - let cc,_,ids = state_coq_ast sign q.a_value in - let ef,c = - List.fold_left - (fun (e,c) id -> - if is_mutable_in_env env id then - if is_write ef id then - Peffect.add_write id e, c - else - Peffect.add_read id e, - subst_in_constr [id,at_id id ""] c - else if is_at id then - let uid,_ = un_at id in - if is_mutable_in_env env uid then - Peffect.add_read uid e, c - else - e,c - else - e,c) - (Peffect.bottom,cc) ids - in - let c = abstract [id,v'] c in - ef, Some { a_name = q.a_name; a_value = c } - -(* transformation of AST into constr in types V and C *) - -let rec cic_type_v env ren = function - | Ref v -> Ref (cic_type_v env ren v) - | Array (com,v) -> - let sign = Pcicenv.now_sign_of ren env in - let c = interp_constr Evd.empty (Global.env_of_context sign) com in - Array (c, cic_type_v env ren v) - | Arrow (bl,c) -> - let bl',ren',env' = - List.fold_left - (fun (bl,ren,env) b -> - let b' = cic_binder env ren b in - let env' = traverse_binders env [b'] in - let ren' = initial_renaming env' in - b'::bl,ren',env') - ([],ren,env) bl - in - let c' = cic_type_c env' ren' c in - Arrow (List.rev bl',c') - | TypePure com -> - let sign = Pcicenv.cci_sign_of ren env in - let c = interp_constr Evd.empty (Global.env_of_context sign) com in - TypePure c - -and cic_type_c env ren ((id,v),e,p,q) = - let v' = cic_type_v env ren v in - let cv = Pmonad.trad_ml_type_v ren env v' in - let efp,p' = state_pre ren env p in - let efq,q' = state_post ren env (id,v',e) q in - let ef = Peffect.union e (Peffect.union efp efq) in - ((id,v'),ef,p',q') - -and cic_binder env ren = function - | (id,BindType v) -> - let v' = cic_type_v env ren v in - let env' = add (id,v') env in - let ren' = initial_renaming env' in - (id, BindType v') - | (id,BindSet) -> (id,BindSet) - | (id,Untyped) -> (id,Untyped) - -and cic_binders env ren = function - [] -> [] - | b::bl -> - let b' = cic_binder env ren b in - let env' = traverse_binders env [b'] in - let ren' = initial_renaming env' in - b' :: (cic_binders env' ren' bl) - - -(* The case of expressions. - * - * Expressions are programs without neither effects nor pre/post conditions. - * But access to variables are allowed. - * - * Here we transform an expression into the corresponding constr, - * the variables still appearing as VAR (they will be abstracted in - * Mlise.trad) - * We collect the pre-conditions (e<N for t[e]) as we traverse the term. - * We also return the effect, which does contain only *read* variables. - *) - -let states_expression ren env expr = - let rec effect pl = function - | Variable id -> - (if is_global id then constant (string_of_id id) else mkVar id), - pl, Peffect.bottom - | Expression c -> c, pl, Peffect.bottom - | Acc id -> mkVar id, pl, Peffect.add_read id Peffect.bottom - | TabAcc (_,id,p) -> - let c,pl,ef = effect pl p.desc in - let pre = Pmonad.make_pre_access ren env id c in - Pmonad.make_raw_access ren env (id,id) c, - (anonymous_pre true pre)::pl, Peffect.add_read id ef - | Apply (p,args) -> - let a,pl,e = effect pl p.desc in - let args,pl,e = - List.fold_right - (fun arg (l,pl,e) -> - match arg with - Term p -> - let carg,pl,earg = effect pl p.desc in - carg::l,pl,Peffect.union e earg - | Type v -> - let v' = cic_type_v env ren v in - (Pmonad.trad_ml_type_v ren env v')::l,pl,e - | Refarg _ -> assert false) - args ([],pl,e) - in - Term.applist (a,args),pl,e - | _ -> invalid_arg "Ptyping.states_expression" - in - let e0,pl0 = state_pre ren env expr.pre in - let c,pl,e = effect [] expr.desc in - let sign = Pcicenv.before_sign_of ren env in - (*i WAS - let c = (Trad.ise_resolve true empty_evd [] (gLOB sign) c)._VAL in - i*) - let ty = simplify_type_of (Global.env_of_context sign) Evd.empty c in - let v = TypePure ty in - let ef = Peffect.union e0 e in - Expression c, (v,ef), pl0@pl - - -(* We infer here the type with effects. - * The type of types with effects (ml_type_c) is defined in the module ProgAst. - * - * A program of the shape {P} e {Q} has a type - * - * V, E, {None|Some P}, {None|Some Q} - * - * where - V is the type of e - * - E = (I,O) is the effect; the input I contains - * all the input variables appearing in P,e and Q; - * the output O contains variables possibly modified in e - * - P is NOT abstracted - * - Q = [y'1]...[y'k][result]Q where O = {y'j} - * i.e. Q is only abstracted over the output and the result - * the other variables now refer to value BEFORE - *) - -let verbose_fix = ref false - -let rec states_desc ren env loc = function - - Expression c -> - let ty = type_of_expression ren env c in - let v = v_of_constr ty in - Expression c, (v,Peffect.bottom) - - | Acc _ -> - failwith "Ptyping.states: term is supposed not to be pure" - - | Variable id -> - let v = type_in_env env id in - let ef = Peffect.bottom in - Variable id, (v,ef) - - | Aff (x, e1) -> - Perror.check_for_reference loc x (type_in_env env x); - let s_e1 = states ren env e1 in - let _,e,_,_ = s_e1.info.kappa in - let ef = add_write x e in - let v = constant_unit () in - Aff (x, s_e1), (v, ef) - - | TabAcc (check, x, e) -> - let s_e = states ren env e in - let _,efe,_,_ = s_e.info.kappa in - let ef = Peffect.add_read x efe in - let _,ty = dearray_type (type_in_env env x) in - TabAcc (check, x, s_e), (ty, ef) - - | TabAff (check, x, e1, e2) -> - let s_e1 = states ren env e1 in - let s_e2 = states ren env e2 in - let _,ef1,_,_ = s_e1.info.kappa in - let _,ef2,_,_ = s_e2.info.kappa in - let ef = Peffect.add_write x (Peffect.union ef1 ef2) in - let v = constant_unit () in - TabAff (check, x, s_e1, s_e2), (v,ef) - - | Seq bl -> - let bl,v,ef,_ = states_block ren env bl in - Seq bl, (v,ef) - - | While(b, invopt, var, bl) -> - let efphi,(cvar,r') = state_var ren env var in - let ren' = next ren [] in - let s_b = states ren' env b in - let s_bl,_,ef_bl,_ = states_block ren' env bl in - let cb = s_b.info.kappa in - let efinv,inv = state_inv ren env invopt in - let _,efb,_,_ = s_b.info.kappa in - let ef = - Peffect.union (Peffect.union ef_bl efb) (Peffect.union efinv efphi) - in - let v = constant_unit () in - let cvar = - let al = List.map (fun id -> (id,at_id id "")) (just_reads ef) in - subst_in_constr al cvar - in - While (s_b,inv,(cvar,r'),s_bl), (v,ef) - - | Lam ([],_) -> - failwith "Ptyping.states: abs. should have almost one binder" - - | Lam (bl, e) -> - let bl' = cic_binders env ren bl in - let env' = traverse_binders env bl' in - let ren' = initial_renaming env' in - let s_e = states ren' env' e in - let v = make_arrow bl' s_e.info.kappa in - let ef = Peffect.bottom in - Lam(bl',s_e), (v,ef) - - (* Connectives AND and OR *) - | SApp ([Variable id], [e1;e2]) -> - let s_e1 = states ren env e1 - and s_e2 = states ren env e2 in - let (_,ef1,_,_) = s_e1.info.kappa - and (_,ef2,_,_) = s_e2.info.kappa in - let ef = Peffect.union ef1 ef2 in - SApp ([Variable id], [s_e1; s_e2]), - (TypePure (constant "bool"), ef) - - (* Connective NOT *) - | SApp ([Variable id], [e]) -> - let s_e = states ren env e in - let (_,ef,_,_) = s_e.info.kappa in - SApp ([Variable id], [s_e]), - (TypePure (constant "bool"), ef) - - | SApp _ -> invalid_arg "Ptyping.states (SApp)" - - (* ATTENTION: - Si un argument réel de type ref. correspond à une ref. globale - modifiée par la fonction alors la traduction ne sera pas correcte. - Exemple: - f=[x:ref Int]( r := !r+1 ; x := !x+1) modifie r et son argument x - donc si on l'applique à r justement, elle ne modifiera que r - mais le séquencement ne sera pas correct. *) - - | Apply (f, args) -> - let s_f = states ren env f in - let _,eff,_,_ = s_f.info.kappa in - let s_args = List.map (states_arg ren env) args in - let ef_args = - List.map - (function Term t -> let (_,e,_,_) = t.info.kappa in e - | _ -> Peffect.bottom) - s_args - in - let _,_,((_,tapp),efapp,_,_) = effect_app ren env s_f s_args in - let ef = - Peffect.compose (List.fold_left Peffect.compose eff ef_args) efapp - in - Apply (s_f, s_args), (tapp, ef) - - | LetRef (x, e1, e2) -> - let s_e1 = states ren env e1 in - let (_,v1),ef1,_,_ = s_e1.info.kappa in - let env' = add (x,Ref v1) env in - let ren' = next ren [x] in - let s_e2 = states ren' env' e2 in - let (_,v2),ef2,_,_ = s_e2.info.kappa in - Perror.check_for_let_ref loc v2; - let ef = Peffect.compose ef1 (Peffect.remove ef2 x) in - LetRef (x, s_e1, s_e2), (v2,ef) - - | Let (x, e1, e2) -> - let s_e1 = states ren env e1 in - let (_,v1),ef1,_,_ = s_e1.info.kappa in - Perror.check_for_not_mutable e1.loc v1; - let env' = add (x,v1) env in - let s_e2 = states ren env' e2 in - let (_,v2),ef2,_,_ = s_e2.info.kappa in - let ef = Peffect.compose ef1 ef2 in - Let (x, s_e1, s_e2), (v2,ef) - - | If (b, e1, e2) -> - let s_b = states ren env b in - let s_e1 = states ren env e1 - and s_e2 = states ren env e2 in - let (_,tb),efb,_,_ = s_b.info.kappa in - let (_,t1),ef1,_,_ = s_e1.info.kappa in - let (_,t2),ef2,_,_ = s_e2.info.kappa in - let ef = Peffect.compose efb (disj ef1 ef2) in - let v = type_v_sup loc t1 t2 in - If (s_b, s_e1, s_e2), (v,ef) - - | LetRec (f,bl,v,var,e) -> - let bl' = cic_binders env ren bl in - let env' = traverse_binders env bl' in - let ren' = initial_renaming env' in - let v' = cic_type_v env' ren' v in - let efvar,var' = state_var ren' env' var in - let phi0 = phi_name () in - let tvar = typed_var ren env' var' in - (* effect for a let/rec construct is computed as a fixpoint *) - let rec state_rec c = - let tf = make_arrow bl' c in - let env'' = add_recursion (f,(phi0,tvar)) (add (f,tf) env') in - let s_e = states ren' env'' e in - if s_e.info.kappa = c then - s_e - else begin - if !verbose_fix then begin msgnl (pp_type_c s_e.info.kappa) end ; - state_rec s_e.info.kappa - end - in - let s_e = state_rec ((result_id,v'),efvar,[],None) in - let tf = make_arrow bl' s_e.info.kappa in - LetRec (f,bl',v',var',s_e), (tf,Peffect.bottom) - - | PPoint (s,d) -> - let ren' = push_date ren s in - states_desc ren' env loc d - - | Debug _ -> failwith "Ptyping.states: Debug: TODO" - - -and states_arg ren env = function - Term a -> let s_a = states ren env a in Term s_a - | Refarg id -> Refarg id - | Type v -> let v' = cic_type_v env ren v in Type v' - - -and states ren env expr = - (* Here we deal with the pre- and post- conditions: - * we add their effects to the effects of the program *) - let (d,(v,e),p1) = - if is_pure_desc ren env expr.desc then - states_expression ren env expr - else - let (d,ve) = states_desc ren env expr.loc expr.desc in (d,ve,[]) - in - let (ep,p) = state_pre ren env expr.pre in - let (eq,q) = state_post ren env (result_id,v,e) expr.post in - let e' = Peffect.union e (Peffect.union ep eq) in - let p' = p1 @ p in - let tinfo = { env = env; kappa = ((result_id,v),e',p',q) } in - { desc = d; - loc = expr.loc; - pre = p'; post = q; (* on les conserve aussi ici pour prog_wp *) - info = tinfo } - - -and states_block ren env bl = - let rec ef_block ren tyres = function - [] -> - begin match tyres with - Some ty -> [],ty,Peffect.bottom,ren - | None -> failwith "a block should contain at least one statement" - end - | (Assert p)::block -> - let ep,c = state_assert ren env p in - let bl,t,ef,ren' = ef_block ren tyres block in - (Assert c)::bl,t,Peffect.union ep ef,ren' - | (Label s)::block -> - let ren' = push_date ren s in - let bl,t,ef,ren'' = ef_block ren' tyres block in - (Label s)::bl,t,ef,ren'' - | (Statement e)::block -> - let s_e = states ren env e in - let (_,t),efe,_,_ = s_e.info.kappa in - let ren' = next ren (get_writes efe) in - let bl,t,ef,ren'' = ef_block ren' (Some t) block in - (Statement s_e)::bl,t,Peffect.compose efe ef,ren'' - in - ef_block ren None bl - |