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___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *)
(* \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$ *)
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
;;
|