1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
|
(************************************************************************)
(* 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 Fillitre *)
(* $Id: pdb.ml,v 1.8.2.1 2004/07/16 19:30:01 herbelin Exp $ *)
open Names
open Term
open Termops
open Nametab
open Constrintern
open Ptype
open Past
open Penv
let cci_global id =
try
global_reference id
with
_ -> raise Not_found
let lookup_var ids locop id =
if List.mem id ids then
None
else begin
try Some (cci_global id)
with Not_found -> Perror.unbound_variable id locop
end
let check_ref idl loc id =
if (not (List.mem id idl)) & (not (Penv.is_global id)) then
Perror.unbound_reference id loc
(* db types : only check the references for the moment *)
let rec check_type_v refs = function
| Ref v ->
check_type_v refs v
| Array (c,v) ->
check_type_v refs v
| Arrow (bl,c) ->
check_binder refs c bl
| TypePure _ ->
()
and check_type_c refs ((_,v),e,_,_) =
check_type_v refs v;
List.iter (check_ref refs None) (Peffect.get_reads e);
List.iter (check_ref refs None) (Peffect.get_writes e)
(* TODO: check_condition on p and q *)
and check_binder refs c = function
| [] ->
check_type_c refs c
| (id, BindType (Ref _ | Array _ as v)) :: bl ->
check_type_v refs v;
check_binder (id :: refs) c bl
| (_, BindType v) :: bl ->
check_type_v refs v;
check_binder refs c bl
| _ :: bl ->
check_binder refs c bl
(* db binders *)
let rec db_binders ((tids,pids,refs) as idl) = function
| [] ->
idl, []
| (id, BindType (Ref _ | Array _ as v)) as b :: rem ->
check_type_v refs v;
let idl',rem' = db_binders (tids,pids,id::refs) rem in
idl', b :: rem'
| (id, BindType v) as b :: rem ->
check_type_v refs v;
let idl',rem' = db_binders (tids,id::pids,refs) rem in
idl', b :: rem'
| ((id, BindSet) as t) :: rem ->
let idl',rem' = db_binders (id::tids,pids,refs) rem in
idl', t :: rem'
| a :: rem ->
let idl',rem' = db_binders idl rem in idl', a :: rem'
(* db programs *)
let db_prog e =
(* tids = type identifiers, ids = variables, refs = references and arrays *)
let rec db_desc ((tids,ids,refs) as idl) = function
| (Variable x) as t ->
(match lookup_var ids (Some e.loc) x with
None -> t
| Some c -> Expression c)
| (Acc x) as t ->
check_ref refs (Some e.loc) x;
t
| Aff (x,e1) ->
check_ref refs (Some e.loc) x;
Aff (x, db idl e1)
| TabAcc (b,x,e1) ->
check_ref refs (Some e.loc) x;
TabAcc(b,x,db idl e1)
| TabAff (b,x,e1,e2) ->
check_ref refs (Some e.loc) x;
TabAff (b,x, db idl e1, db idl e2)
| Seq bl ->
Seq (List.map (function
Statement p -> Statement (db idl p)
| x -> x) bl)
| If (e1,e2,e3) ->
If (db idl e1, db idl e2, db idl e3)
| While (b,inv,var,bl) ->
let bl' = List.map (function
Statement p -> Statement (db idl p)
| x -> x) bl in
While (db idl b, inv, var, bl')
| Lam (bl,e) ->
let idl',bl' = db_binders idl bl in Lam(bl', db idl' e)
| Apply (e1,l) ->
Apply (db idl e1, List.map (db_arg idl) l)
| SApp (dl,l) ->
SApp (dl, List.map (db idl) l)
| LetRef (x,e1,e2) ->
LetRef (x, db idl e1, db (tids,ids,x::refs) e2)
| Let (x,e1,e2) ->
Let (x, db idl e1, db (tids,x::ids,refs) e2)
| LetRec (f,bl,v,var,e) ->
let (tids',ids',refs'),bl' = db_binders idl bl in
check_type_v refs' v;
LetRec (f, bl, v, var, db (tids',f::ids',refs') e)
| Debug (s,e1) ->
Debug (s, db idl e1)
| Expression _ as x -> x
| PPoint (s,d) -> PPoint (s, db_desc idl d)
and db_arg ((tids,_,refs) as idl) = function
| Term ({ desc = Variable id } as t) ->
if List.mem id refs then Refarg id else Term (db idl t)
| Term t -> Term (db idl t)
| Type v as ty -> check_type_v refs v; ty
| Refarg _ -> assert false
and db idl e =
{ desc = db_desc idl e.desc ;
pre = e.pre; post = e.post;
loc = e.loc; info = e.info }
in
let ids = Termops.ids_of_named_context (Global.named_context ()) in
(* TODO: separer X:Set et x:V:Set
virer le reste (axiomes, etc.) *)
let vars,refs = all_vars (), all_refs () in
db ([],vars@ids,refs) e
;;
|