Project

General

Profile

Download (32.2 KB) Statistics
| Branch: | Tag: | Revision:
1
open Format
2
open LustreSpec
3
open Machine_code
4
open Corelang
5
open C_backend_common
6
open C_backend_spec
7
open Utils
8
open Types
9

    
10
let fullExists = true
11

    
12
let rec list_to_partial l = match l with
13
  | []   -> [[]]
14
  | _::q -> l::(list_to_partial q)
15

    
16

    
17
(* Print a function call/declaration in acsl *) 
18
let pp_acsl_fun name fmt args =
19
    fprintf fmt "%s(@[<v>%a@])"
20
      name
21
      (Utils.fprintf_list ~sep:",@ " (fun fmt f-> f fmt)) args
22

    
23
(* Print an invariant call/decl in acsl *)
24
let pp_acsl_fun_init name self inst fmt mem =
25
  let arg = fun fmt-> (match inst, mem with
26
    | x,  None    -> fprintf fmt "%a %s" pp_machine_memtype_name name self
27
    | "", Some "" -> fprintf fmt "%s" self
28
    | "", Some m  -> fprintf fmt "\\at(*%s, %s)" self m
29
    | x,  Some "" -> fprintf fmt "%s.%s" self inst
30
    | x,  Some m  -> fprintf fmt "\\at(%s->%s, %s)" self inst m)
31
  in
32
  pp_acsl_fun ("init_"^name) fmt [arg]
33

    
34

    
35
let preprocess_acsl_instr calls outputs instr =
36
  match instr with 
37
    | MStep ([i0], i, vl) when Basic_library.is_internal_fun i && (not (List.mem i0 outputs)) ->
38
      Some (i0, Fun (i, vl))
39
    | MStep ([i0], i, vl) when (not (Basic_library.is_internal_fun i)) && (node_name (fst (List.assoc i calls)) = "_arrow") && (not (List.mem i0 outputs)) ->
40
      assert (List.length vl == 2);
41
      Some (i0, Fun ("arrow_"^i, vl))
42
    | MLocalAssign (i,v) when not (List.mem i outputs) ->
43
      Some (i, v)
44
    | _ -> None
45

    
46

    
47
let pp_cast fmt = function
48
  | Types.Tbool           -> fprintf fmt "(_Bool)"
49
  | Types.Treal           -> fprintf fmt "(double)"
50
  | Types.Tint            -> fprintf fmt "(int)"
51
  | _ -> assert false
52

    
53
let getFunType i args =
54
  match i, args with
55
  | "ite", [v1; v2; v3] -> v2
56
  | "uminus", [v] -> v
57
  | "not", [v] -> v
58
  | "impl", [v1; v2] -> v1
59
  | "=", [v1; v2] -> Types.Tbool
60
  | "mod", [v1; v2] -> v1
61
  | "xor", [v1; v2] -> v1
62
  | _, [v1; v2] -> v1
63
  | _ -> assert false
64

    
65
let rec get_val_type v =
66
match v with 
67
| Cst _
68
| LocalVar _ 
69
| StateVar _-> Machine_code.get_val_type v
70
| Fun (n, vl) -> getFunType n (List.map get_val_type vl)
71
| Array _
72
| Access _
73
| Power _ -> assert false
74

    
75
let get_var_type t = (Types.repr t.var_type).Types.tdesc
76

    
77
(* Print a machine instruction in acsl for transition lemma *) 
78
let rec pp_acsl_instr_assert init vars instances calls self pointer fmt instr =
79
  let mem1 = if init then self else ("\\at(*"^self^", Pre)") in
80
  let mem2 = if init then self else ("(*"^self^")") in
81
  match instr with 
82
    | MReset i ->
83
      let (node, static) = List.assoc i calls in
84
      assert (List.length static == 0);
85
      if node_name node = "_arrow" then
86
        fprintf fmt "(%s.%s._reg._first==1)" self i
87
      else
88
        pp_acsl_fun_init (node_name node) self i fmt (Some "")
89
    | MLocalAssign (i,v) -> 
90
      (match i.var_type.tdesc with Tbool -> fprintf fmt "((!%a) == (!%a))" | _ -> fprintf fmt "(%a == %a)")
91
      (pp_acsl_var_read pointer) i
92
      (pp_acsl_val mem1 (pp_acsl_var_read pointer)) v
93
    | MStateAssign (i,v) ->
94
      (match i.var_type.tdesc with Tbool -> fprintf fmt "((!%a) == (!%a))" | _ -> fprintf fmt "(%a == %a)")
95
      (pp_acsl_val mem2 (pp_acsl_var_read pointer)) (StateVar i)
96
      (pp_acsl_val mem1 (pp_acsl_var_read pointer)) v
97
    | MStep ([i0], i, vl) when Basic_library.is_internal_fun i  ->
98
      pp_acsl_instr_assert init vars calls instances self pointer fmt (MLocalAssign (i0, Fun (i, vl)))
99
    | MStep ([i0], i, [x;y]) when (not (Basic_library.is_internal_fun i)) && (node_name (fst (List.assoc i calls)) = "_arrow") ->
100
      fprintf fmt "(%a==(%s.%s._reg._first?(%a):(%a))) && (%s.%s._reg._first==0)"
101
        (pp_acsl_var_read pointer) i0
102
        mem1 i
103
        (pp_acsl_val mem1 (pp_acsl_var_read [])) x
104
        (pp_acsl_val mem1 (pp_acsl_var_read [])) y
105
        mem2 i
106
    | MStep (il, i, vl) ->
107
      let pp_val fmt x = (match get_val_type x with Types.Tbool -> fprintf fmt "((%a)?1:0)" | _ -> fprintf fmt "%a") (pp_acsl_val mem1 (pp_acsl_var_read [])) x in
108
      pp_acsl_fun ("Ctrans_"^(node_name (fst (List.assoc i calls)))) fmt
109
      ((List.map (fun x fmt-> fprintf fmt "%a %a" pp_cast (get_val_type x) pp_val x) vl)@
110
      (List.map (fun x fmt-> fprintf fmt "%a" (*pp_cast (get_var_type x)*) (pp_acsl_var_read []) x) il)@
111
        (try ignore(List.assoc i instances);[(fun fmt->fprintf fmt "%s.%s" mem1 i);(fun fmt->fprintf fmt "%s.%s" mem2 i)] with Not_found -> []))
112
    | MBranch (g,hl) -> assert false (*TODO: useless : ????
113
      let t = fst (List.hd hl) in
114
      if hl <> [] && (t = tag_true || t = tag_false) then
115
        let tl = try List.assoc tag_true  hl with Not_found -> [] in
116
        let el = try List.assoc tag_false hl with Not_found -> [] in
117
        fprintf fmt "((%a)?(%a%s):(%a%s))"
118
          (pp_acsl_val mem1 (pp_acsl_var_read pointer)) g
119
          (Utils.fprintf_list ~sep:"&& " (pp_acsl_instr init vars calls self pointer)) tl
120
          (if List.length tl == 0 then "1" else "")
121
          (Utils.fprintf_list ~sep:"&& " (pp_acsl_instr init vars calls self pointer)) el
122
          (if List.length el == 0 then "1" else "")
123
      else assert false*)
124

    
125
(* Print all machine instructions in acsl for transition lemma *) 
126
let pp_acsl_instrs_assert init outputs self pointer instances calls vars fmt instrs =
127
  fprintf fmt "     ensures %a;"
128
    (Utils.fprintf_list ~sep:";@,     ensures " (pp_acsl_instr_assert init vars instances calls self (pointer@outputs)))
129
    instrs
130

    
131
(* Print a machine instruction in acsl for transition lemma *) 
132
let rec pp_acsl_instr init vars instances calls self pointer fmt instr =
133
  let mem1 = if init then self else (self^"1") in
134
  let mem2 = if init then self else (self^"2") in
135
  match instr with 
136
    | MReset i ->
137
      let (node, static) = List.assoc i calls in
138
      assert (List.length static == 0);
139
      if node_name node = "_arrow" then
140
        fprintf fmt "(%s.%s._reg._first==1)" self i
141
      else
142
        pp_acsl_fun_init (node_name node) self i fmt (Some "")
143
    | MLocalAssign (i,v) -> 
144
      (match i.var_type.tdesc with Tbool -> fprintf fmt "((!%a) == (!%a))" | _ -> fprintf fmt "(%a == %a)")
145
      (pp_acsl_var_read pointer) i
146
      (pp_acsl_val mem1 (pp_acsl_var_read pointer)) v
147
    | MStateAssign (i,v) ->
148
      (match i.var_type.tdesc with Tbool -> fprintf fmt "((!%a) == (!%a))" | _ -> fprintf fmt "(%a == %a)")
149
      (pp_acsl_val mem2 (pp_acsl_var_read pointer)) (StateVar i)
150
      (pp_acsl_val mem1 (pp_acsl_var_read pointer)) v
151
    | MStep ([i0], i, vl) when Basic_library.is_internal_fun i  ->
152
      pp_acsl_instr init vars calls instances self pointer fmt (MLocalAssign (i0, Fun (i, vl)))
153
    | MStep ([i0], i, [x;y]) when (not (Basic_library.is_internal_fun i)) && (node_name (fst (List.assoc i calls)) = "_arrow") ->
154
      fprintf fmt "(%a==(%s1.%s._reg._first?(%a):(%a))) && (%s2.%s._reg._first==0)"
155
        (pp_acsl_var_read pointer) i0
156
        self i
157
        (pp_acsl_val mem1 (pp_acsl_var_read [])) x
158
        (pp_acsl_val mem1 (pp_acsl_var_read [])) y
159
        self i
160
    | MStep (il, i, vl) ->
161
      let pp_val fmt x = (match get_val_type x with Types.Tbool -> fprintf fmt "%a" | _ -> fprintf fmt "%a") (pp_acsl_val mem1 (pp_acsl_var_read [])) x in
162
      pp_acsl_fun ("Ctrans_"^(node_name (fst (List.assoc i calls)))) fmt
163
      ((List.map (fun x fmt-> fprintf fmt "%a %a" pp_cast (get_val_type x) pp_val x) vl)@
164
      (List.map (fun x fmt-> fprintf fmt "%a" (*pp_cast (get_var_type x)*) (pp_acsl_var_read []) x) il)@
165
        (try ignore(List.assoc i instances);[(fun fmt->fprintf fmt "%s1.%s" self i);(fun fmt->fprintf fmt "%s2.%s" self i)] with Not_found -> []))
166
    | MBranch (g,hl) -> assert false (*TODO: useless : ????
167
      let t = fst (List.hd hl) in
168
      if hl <> [] && (t = tag_true || t = tag_false) then
169
        let tl = try List.assoc tag_true  hl with Not_found -> [] in
170
        let el = try List.assoc tag_false hl with Not_found -> [] in
171
        fprintf fmt "((%a)?(%a%s):(%a%s))"
172
          (pp_acsl_val mem1 (pp_acsl_var_read pointer)) g
173
          (Utils.fprintf_list ~sep:"&& " (pp_acsl_instr init vars calls self pointer)) tl
174
          (if List.length tl == 0 then "1" else "")
175
          (Utils.fprintf_list ~sep:"&& " (pp_acsl_instr init vars calls self pointer)) el
176
          (if List.length el == 0 then "1" else "")
177
      else assert false*)
178

    
179
(* Print all machine instructions in acsl for transition lemma *) 
180
let pp_acsl_instrs init outputs self pointer instances calls vars fmt instrs =
181
  if List.length instrs == 0 then fprintf fmt "\\true" else
182
  let handle (locals, instrs) i =
183
    match preprocess_acsl_instr calls outputs i with
184
      | None    -> (locals, i::instrs)
185
      | Some l  -> (l::locals, instrs)
186
  in
187
  let pp_let fmt (i, v) =
188
    match v with
189
      | Fun (s, [x;y]) when String.length s >= 6 && String.sub s 0 6 = "arrow_" ->
190
        let var = String.sub s 6 (String.length s - 6) in
191
        fprintf fmt "\\let %a = %s1.%s._reg._first?%a:%a; (%s2.%s._reg._first==0) &&"
192
          (pp_acsl_var_read pointer) i
193
          self var
194
          (pp_acsl_val (self^"1") (pp_acsl_var_read [])) x
195
          (pp_acsl_val (self^"1") (pp_acsl_var_read [])) y
196
          self var
197
      | _ ->
198
        fprintf fmt "\\let %a = %a;"
199
          (pp_acsl_var_read pointer) i
200
          (pp_acsl_val (self^"1") (pp_acsl_var_read pointer)) v
201
  in
202
  let (locals, instrs) = if fullExists then ([], instrs) else List.fold_left handle ([], []) instrs in
203
  fprintf fmt "%a@,%a"
204
    (Utils.fprintf_list ~sep:"@," pp_let)
205
    (List.rev locals)
206
    (Utils.fprintf_list ~sep:" &&@," (pp_acsl_instr init vars instances calls self pointer))
207
    instrs
208

    
209
(* Take a dependance and print it for invariant predicate *)
210
(*
211
let pp_acsl_dep self instances fmt = function
212
  | Dep_Var s -> fprintf fmt "%s2._reg.%s == %s1._reg.%s" self s self s
213
  | Dep_Node s ->
214
    pp_acsl_fun ("inv_"^(node_name (fst (List.assoc s instances)))) fmt [fun fmt->fprintf fmt "%s1.%s" self i];
215
    fprintf fmt "&&@, %t == %t" (pp_acsl_at self s)
216
      (pp_acsl_at self s)
217
*)
218

    
219
(*
220
Require Why3.
221
intros.
222
unfold P_trans_AltitudeControl.
223
repeat split.
224
why3 "Z3" timelimit 10.
225
why3 "Z3" timelimit 10.
226
why3 "Z3" timelimit 10.
227
why3 "Z3" timelimit 10.
228
why3 "Z3" timelimit 10.
229
why3 "Z3" timelimit 10.
230
why3 "Z3" timelimit 10.
231
why3 "Z3" timelimit 10.
232
why3 "Z3" timelimit 10.
233
why3 "Z3" timelimit 10.
234
why3 "Z3" timelimit 10.
235
why3 "Z3" timelimit 10.
236
why3 "Z3" timelimit 10.
237
why3 "Z3" timelimit 10.
238
why3 "Z3" timelimit 10.
239
why3 "Z3" timelimit 10.
240
why3 "Z3" timelimit 10.
241
why3 "Z3" timelimit 10.
242
assert (a_9 = F_AltitudeControl_mem_ni_1 a_6).
243
why3 "Z3" timelimit 10.
244
assert (a_10 = F_AltitudeControl_mem_ni_1 a_7).
245
unfold F_AltitudeControl_mem_ni_1.
246
unfold a_7.
247
unfold Load_S_AltitudeControl_mem.
248
unfold a_10.
249
unfold a_8.
250
unfold havoc in H36.
251
unfold get.
252
clear.
253
rewrite <- H48.
254
rewrite <- H49.
255
apply H47.
256
*)
257

    
258
(* Print a transition call/decl in acsl *)
259
let pp_acsl_fun_trans infos pre name inputs outputs suffix flag_output self flag_mem locals fmt existential =
260
  let (locals, existential) = (*([], match existential with None -> None | Some x -> Some []) else*)
261
  match infos with
262
    | None -> (locals, existential)
263
    | Some (instrs, calls) ->
264
      let nonlocals = List.fold_left (fun l x-> match preprocess_acsl_instr calls outputs x with | Some (i, _) -> i::l | None -> l) [] instrs in
265
      (
266
        (if not fullExists then List.filter (fun x-> not (List.mem x nonlocals)) else fun x -> x) locals,
267
        match existential with None -> None | Some existential -> Some ((if not fullExists then List.filter (fun x-> not (List.mem x nonlocals)) else fun x -> x) existential)
268
      )
269
  in
270
  let mems = function 1 -> "Pre" | 2 -> "Here" | _ -> assert false in
271
  let pp_self_read =
272
    if flag_mem then fun i fmt-> (match i with 1 -> fprintf fmt "\\at(*%s, Pre)" self | 2 -> fprintf fmt "(*%s)" self | _ -> assert false)
273
    else fun i fmt-> fprintf fmt "%s%i" self (match suffix with None -> i | Some s -> s+i-1)
274
  in
275
  let (pp_var, pp_self) =
276
    match existential with
277
      | None    -> (pp_acsl_var_decl, (fun i fmt-> fprintf fmt "%a %s%i" pp_machine_memtype_name name self i))
278
      | Some ex -> (if List.length ex != 0 then fprintf fmt "\\exists %a;@," (Utils.fprintf_list ~sep:";@,\\exists " pp_acsl_var_decl) ex);
279
                   (pp_acsl_var_read (if flag_output then outputs else []), pp_self_read)
280
  in
281
  let pp_vars = List.map (fun x fmt-> match suffix with None-> pp_var fmt x | Some i -> fprintf fmt "%a%i" pp_var x (i+1)) in
282
    (pp_acsl_fun (pre^"trans_"^name)) fmt
283
    ((pp_vars (inputs@outputs))@(if not (self = "") then [pp_self 1;pp_self 2] else [])@(pp_vars locals))
284

    
285
(* Print an invariant call/decl in acsl *)
286
let pp_acsl_fun_inv depth name self fmt mem =
287
  let arg = fun fmt-> (match mem with
288
    | None -> fprintf fmt "%a %s%i" pp_machine_memtype_name name self depth
289
    | Some "" -> fprintf fmt "%s" self
290
    | Some "Here" -> fprintf fmt "*%s" self
291
    | Some m -> fprintf fmt "\\at(*%s, %s)" self m)
292
  in
293
  pp_acsl_fun ("inv_"^name) fmt [arg]
294

    
295
(* Print an invariant call/decl in acsl *)
296
let pp_acsl_inv depth name inputs outputs self fmt spec =
297
  let rec iter base x = function
298
    | i when i = base-1 -> []
299
    | i -> (i, x)::(iter base x (i-1))
300
  in
301
  let rec iterList base = function
302
    | []   -> []
303
    | t::q -> (iter base t depth)@(iterList base q)
304
  in
305
  let trans_pred fmt i =
306
    fprintf fmt "%a" (pp_acsl_fun_trans  None "C" name inputs outputs (Some i) false self false []) (Some [])
307
  in
308
  let pp_eexpr_expr self i j fmt ee = 
309
    fprintf fmt "spec_%i(%a, %s%i)" ee.muid (Utils.fprintf_list ~sep:", " (fun fmt x-> fprintf fmt "%a%i" (pp_acsl_var_read []) x j)) ee.mmstep_logic.step_inputs self i
310
  in
311
  let spec_pred cor preds fmt i =
312
    let j = if cor then i + 1 else i in
313
    fprintf fmt "(%a)" (Utils.fprintf_list ~sep:"&&@," (pp_eexpr_expr self i j)) preds
314
  in
315
  let aux fmt base =
316
    let selfs = iter base self (depth-1) in
317
    let ios = iterList (base + 1) (inputs@outputs) in
318
    (if List.length selfs == 0 && List.length ios == 0 then 
319
      fprintf fmt "(%a%t%a%t%t)"
320
     else
321
      fprintf fmt "(\\exists %a%t%a;@,%a%t%a%t%t)"
322
        (Utils.fprintf_list ~sep:", "   (fun fmt (i, x)-> fprintf fmt "%a %s%i" pp_machine_memtype_name name self i)) selfs
323
        (Utils.pp_final_char_if_non_empty ", " (iter base self (depth-1)))
324
        (Utils.fprintf_list ~sep:", "   (fun fmt (i, x)-> fprintf fmt "%a%i" pp_acsl_var_decl x i)) ios
325
    )
326
      (Utils.fprintf_list ~sep:"&&@," (fun fmt (i, f)-> fprintf fmt "%a" f i)) (iter base trans_pred (depth-1))
327
      (Utils.pp_final_char_if_non_empty "&&@," (iter base trans_pred (depth-1))) 
328
      (Utils.fprintf_list ~sep:"&&@," (fun fmt (i, f)-> fprintf fmt "%a" f i)) (iter base (spec_pred true spec.m_requires) (depth-1))
329
      (Utils.pp_final_char_if_non_empty "&&@," (iter base (spec_pred true spec.m_requires) (depth-1))) 
330
      (fun fmt->
331
        if base == 0 then
332
          Utils.fprintf_list ~sep:"&&@," (fun fmt (i, f)-> fprintf fmt "%a" f i) fmt (iter (base+1) (spec_pred false spec.m_ensures) depth)
333
        else
334
          pp_acsl_fun_init name (self^(string_of_int base)) "" fmt (Some "")
335
      )
336
  in
337
  Utils.fprintf_list ~sep:"||@," (fun fmt (i, f)-> fprintf fmt "%a" f i) fmt (iter 0 aux depth)
338

    
339
(* Print the invariant lemma *)
340
let pp_acsl_lem_inv depth name inputs outputs self fmt spec =
341
  let pp_eexpr_expr self j fmt ee =
342
    fprintf fmt "spec_%i(%a, %s%i)" ee.muid (Utils.fprintf_list ~sep:", " (pp_acsl_var_read [])) ee.mmstep_logic.step_inputs self j
343
  in
344
  fprintf fmt "\\forall %a %s1, %s2, %a;@,%a==>@,%a==>@,%a%t%a"
345
    pp_machine_memtype_name name self self
346
    (Utils.fprintf_list ~sep:", " pp_acsl_var_decl) (inputs@outputs)
347
    (pp_acsl_fun_inv depth name (self^"1")) (Some "")
348
    (pp_acsl_fun_trans None "C" name inputs outputs None false self false []) (Some [])
349
    (Utils.fprintf_list ~sep:"==>@," (pp_eexpr_expr self 1)) spec.m_requires
350
    (Utils.pp_final_char_if_non_empty "==>@," spec.m_requires)
351
    (pp_acsl_fun_inv depth name (self^"2")) (Some "")
352

    
353
(* Print lemma init *)
354
let pp_acsl_lem_init k depth name inputs outputs self fmt spec =
355
  let rec iter base x = function
356
    | i when i = base-1 -> []
357
    | i -> (i, x)::(iter base x (i-1))
358
  in
359
  let rec iterList base = function
360
    | []   -> []
361
    | t::q -> (iter base t depth)@(iterList base q)
362
  in
363
  let trans_pred fmt i =
364
    fprintf fmt "%a" (pp_acsl_fun_trans  None "C" name inputs outputs (Some i) false self false []) (Some [])
365
  in
366
  let spec_pred fmt i =
367
    let pp_eexpr_expr self j fmt ee = 
368
      fprintf fmt "spec_%i(%a, %s%i)" ee.muid (Utils.fprintf_list ~sep:", " (fun fmt x-> fprintf fmt "%a%i" (pp_acsl_var_read []) x i)) ee.mmstep_logic.step_inputs self j
369
    in
370
    fprintf fmt "%a%t(%a)"
371
    (Utils.fprintf_list ~sep:"==>@," ((fun fmt (w, x)-> fprintf fmt "%a"
372
      (Utils.fprintf_list ~sep:"==>@," (pp_eexpr_expr self (w))) spec.m_requires
373
    ))) (iter k None (depth -1))
374
    (Utils.pp_final_char_if_non_empty "==>@," spec.m_requires)
375
    (Utils.fprintf_list ~sep:"&&@," (pp_eexpr_expr self (i))) spec.m_ensures
376
  in
377
  let aux fmt base =
378
    let selfs = iter base self (depth) in
379
    let ios = iterList (base + 1) (inputs@outputs) in
380
    (if List.length selfs == 0 && List.length ios == 0 then 
381
      fprintf fmt "(%a%t%t)"
382
     else
383
      fprintf fmt "\\forall %a%t%a;@,%a%t%t"
384
        (Utils.fprintf_list ~sep:", "   (fun fmt (i, x)-> fprintf fmt "%a %s%i" pp_machine_memtype_name name self i)) selfs
385
        (Utils.pp_final_char_if_non_empty ", " (iter base self (depth-1)))
386
        (Utils.fprintf_list ~sep:", "   (fun fmt (i, x)-> fprintf fmt "%a%i" pp_acsl_var_decl x i)) ios
387
    )
388
      (Utils.fprintf_list ~sep:"==>@," (fun fmt (i, f)-> fprintf fmt "%a" f i)) (iter base trans_pred (depth-1))
389
      (Utils.pp_final_char_if_non_empty "==>@," (iter base trans_pred (depth-1))) 
390
      (fun fmt->
391
          pp_acsl_fun_init name (self^(string_of_int base)) "" fmt (Some "")
392
      )
393
  in
394
  fprintf fmt "%a ==> %a" aux k spec_pred depth
395

    
396
(* Print the spec lemma *)
397
let pp_acsl_lem_spec depth name inputs outputs self fmt spec =
398
  let pp_eexpr_expr self j fmt ee =
399
    fprintf fmt "spec_%i(%a, %s%i)" ee.muid (Utils.fprintf_list ~sep:", " (pp_acsl_var_read [])) ee.mmstep_logic.step_inputs self j
400
  in
401
  fprintf fmt "\\forall %a %s1, %s2, %a;@,%a==>@,%a==>@,%a%t%a"
402
    pp_machine_memtype_name name self self
403
    (Utils.fprintf_list ~sep:", " pp_acsl_var_decl) (inputs@outputs)
404
    (pp_acsl_fun_inv depth name (self^"1")) (Some "")
405
    (pp_acsl_fun_trans None "C" name inputs outputs None false self false []) (Some [])
406
    (Utils.fprintf_list ~sep:"==>@," (pp_eexpr_expr self 1)) spec.m_requires
407
    (Utils.pp_final_char_if_non_empty "==>@," spec.m_requires)
408
    (Utils.fprintf_list ~sep:"&&@," (pp_eexpr_expr self 2)) spec.m_ensures
409

    
410
let getDepth m =
411
  try (
412
    match (List.assoc ["k"] (List.flatten (List.map (fun x-> x.annots) m.mannot))).eexpr_qfexpr.expr_desc with
413
      | (Expr_const (Const_int k)) -> k
414
      | _ -> 0
415
  ) with Not_found -> 0
416

    
417
(* Get the instructions from acsl spec effect *)
418
let get_instrs_effect spec =
419
  let effects = spec.m_requires@spec.m_ensures@
420
    (List.fold_left 
421
       (fun accu (_,assumes, ensures) -> assumes@ensures@accu) 
422
      [] spec.m_behaviors)
423
  in
424
  let effects = List.filter (fun ee -> ee.mmstep_effects.step_instrs <> []) effects in
425
  List.flatten (List.map (fun e -> e.mmstep_effects.step_instrs) effects)
426

    
427
let get_instrs_effect_init spec =
428
  let effects = spec.m_requires@spec.m_ensures@
429
    (List.fold_left 
430
       (fun accu (_,assumes, ensures) -> assumes@ensures@accu) 
431
       [] spec.m_behaviors)
432
  in
433
  
434
  let effects = List.filter (fun ee -> ee.mminit <> []) effects in
435
  List.flatten (List.map (fun e -> e.mminit) effects)
436

    
437
module Make = 
438
  functor (SpecArg: SPECARG) -> 
439
struct
440
  
441
  open SpecArg
442

    
443
  module Spec = Make(SpecArg)
444

    
445
  let init m = Spec.init m
446

    
447
  module HdrMod = struct
448

    
449
    (* Print all the proof stuff *)
450
    let pp_acsl_def_trans stateless fmt m =
451
      let name = m.mname.node_id in
452
      let inputs = m.mstep.step_inputs in
453
      let outputs = m.mstep.step_outputs in
454
      let locals = m.mstep.step_locals in
455
      let memory = m.mmemory in
456
      let vars = inputs@outputs@locals@memory in
457
      let depth = getDepth m in
458
      let instrs = match m.mspec with None -> [] | Some spec -> get_instrs_effect (Spec.get_spec m.mname) in
459
      let instrs_init =  match m.mspec with None -> [] | Some spec -> get_instrs_effect_init (Spec.get_spec m.mname) in
460
      let induction = (not stateless) && (getDepth m != 0) in
461
      if m.mname.node_id <> arrow_id then (
462
        let self = if stateless then "" else mk_self m in
463
        fprintf fmt "/*@@ @[<v 3>predicate %a =@;%a;@]@;*/@."
464
          (pp_acsl_fun_trans (Some (m.mstep.step_instrs, m.mcalls)) "" name inputs outputs None false self false locals) None
465
            (pp_acsl_instrs false outputs self [] m.minstances m.mcalls vars) (m.mstep.step_instrs@instrs);
466
        fprintf fmt "/*@@ @[<v 3>predicate %a =@;%a;@]@;*/@."
467
          (pp_acsl_fun_trans None "C" name inputs outputs None false self false []) None
468
            (pp_acsl_fun_trans (Some (m.mstep.step_instrs, m.mcalls)) "" name inputs outputs None false self false locals) (Some locals);
469
        (if not stateless then fprintf fmt "/*@@ @[<v 3>predicate %a =@;%a;@]@;*/@."
470
          (pp_acsl_fun_init name self "") None
471
            (pp_acsl_instrs true [] self [] m.minstances m.mcalls vars) (m.minit@instrs_init));
472
        if induction then (
473
        match m.mspec with None -> () | Some spec -> (
474
          let spec = (Spec.get_spec m.mname) in
475
          fprintf fmt "/*@@ @[<v 3>predicate %a =@;%a;@]@;*/@." (pp_acsl_fun_inv depth name self) None (pp_acsl_inv depth name inputs outputs self) spec;
476
          for i = 0 to depth-1 do
477
            fprintf fmt "/*@@ @[<v 3>lemma inv_init_%i_%s : @;%a;@]@;*/@." (depth-i) name (pp_acsl_lem_init i depth name inputs outputs self) spec;
478
          done;
479
          fprintf fmt "/*@@ @[<v 3>lemma inv_spec_%s : @;%a;@]@;*/@." name (pp_acsl_lem_spec depth name inputs outputs self) spec;
480
          fprintf fmt "/*@@ @[<v 3>lemma inv_inv_%s : @;%a;@]@;*/@." name (pp_acsl_lem_inv depth name inputs outputs self) spec
481
        )
482
      ))
483
    let _print_machine_decl_step_fun_prefix stateless fmt m =
484
      let self = mk_self m in
485
      let induction = (not stateless) && (getDepth m != 0) in
486
      let pre_inv = fun fmt -> fprintf fmt "requires %a;@," (pp_acsl_fun_inv (getDepth m) m.mname.node_id self) (Some "Here") in
487
      let post_inv = fun fmt -> fprintf fmt "ensures %a;@," (pp_acsl_fun_inv (getDepth m) m.mname.node_id self) (Some "Here") in
488
        let post_trans = fun fmt -> fprintf fmt "ensures %a;@," (pp_acsl_fun_trans None "C" m.mname.node_id m.mstep.step_inputs m.mstep.step_outputs None true (if stateless then "" else self) true []) (Some []) in
489
      let pre = match m.mspec with
490
        | Some _ when induction -> pre_inv
491
        | _ -> fun fmt -> ()
492
      in
493
      let post = match m.mspec with
494
        | Some _ when induction -> fun fmt -> fprintf fmt "%t%t" post_inv post_trans
495
        | _ -> post_trans
496
      in
497
      Spec.HdrMod._print_machine_decl_step_fun_prefix stateless pre post fmt m
498

    
499
    let has_spec_mem m = Spec.HdrMod.has_spec_mem m
500
    let pp_registers_struct fmt m = Spec.HdrMod.pp_registers_struct fmt m
501
    let print_machine_decl_prefix fmt m =
502
        let mems = Machine_code.get_mems m machines in
503
        fprintf fmt "%a%a"
504
          Spec.HdrMod.print_machine_decl_prefix m
505
          (pp_acsl_def_trans (List.length mems == 0)) m
506
    let print_machine_decl_step_fun_prefix fmt m = _print_machine_decl_step_fun_prefix false fmt m
507
    
508
    let print_machine_decl_init_fun_prefix fmt m =
509
      let self = mk_self m in
510
      let post fmt = 
511
          fprintf fmt "ensures %a;@." (pp_acsl_fun_init m.mname.node_id self "") (Some "Here");
512
        match m.mspec with
513
        | Some _ when getDepth m != 0 ->
514
            fprintf fmt "ensures %a;@." (pp_acsl_fun_inv (getDepth m) m.mname.node_id self) (Some "Here")
515
        | _ -> ()
516
          
517
      in
518
      Spec.HdrMod._print_machine_decl_init_fun_prefix (fun fmt-> ()) post fmt m
519
    
520
    let print_machine_decl_stateless_fun_prefix fmt m = _print_machine_decl_step_fun_prefix true fmt m
521
    
522
    let print_global_decl fmt = fprintf fmt "/*@@ @[<v 3>lemma missing: \\forall _Bool x; (x != 0) <==> (((int) x) != 0);*/@."
523
  end
524

    
525
  module SrcMod =
526
  struct
527
    let print_step_code_prefix stateless fmt m =
528
      let inputs = m.mstep.step_inputs in
529
      let outputs = m.mstep.step_outputs in
530
      let locals = m.mstep.step_locals in
531
      let mems = Machine_code.get_mems m machines in
532
      let self = if List.length mems == 0 then "" else mk_self m in
533
      fprintf fmt "/*@@ensures %a;@,%a*/@,{@," 
534
        (pp_acsl_fun_trans None "C" m.mname.node_id m.mstep.step_inputs m.mstep.step_outputs None true (if stateless then "" else self) true []) (Some [])
535
        (C_backend_spec.pp_assigns [] stateless machines) m
536
    let print_step_code_midfix stateless fmt m =
537
      let inputs = m.mstep.step_inputs in
538
      let outputs = m.mstep.step_outputs in
539
      let locals = m.mstep.step_locals in
540
      let mems = Machine_code.get_mems m machines in
541
      let self = if List.length mems == 0 then "" else mk_self m in
542
      let instrs = match m.mspec with None -> [] | Some spec -> get_instrs_effect (Spec.get_spec m.mname) in
543
      let memory = m.mmemory in
544
      let vars = inputs@outputs@locals@memory in
545
      let filtered_existencials = (if fullExists then 
546
        let nonlocals = List.fold_left (fun l x-> match preprocess_acsl_instr m.mcalls outputs x with | Some (i, _) -> i::l | None -> l) [] m.mstep.step_instrs in
547
        List.filter (fun x-> not (List.mem x nonlocals))else fun x -> x) locals
548
      in
549
      Format.fprintf fmt "@,/* Asserting trans predicate: locals are [%a] */@,"
550
        (fprintf_list ~sep:", " Printers.pp_var) filtered_existencials;
551
      (Utils.fprintf_list ~sep:"@," 
552
        (fun fmt x -> 
553
          fprintf fmt "/*@@ensures %a;@,%a*/@,{@," 
554
        (pp_acsl_fun_trans 
555
           (Some (m.mstep.step_instrs, m.mcalls)) 
556
           "" (* no predicate prefix *)
557
           m.mname.node_id
558
           inputs 
559
           outputs 
560
           None 
561
           true
562
           self
563
           true
564
           locals
565
        ) 
566
        (Some x) 
567
        (C_backend_spec.pp_assigns (List.map (fun x fmt-> Printers.pp_var_name fmt x) locals) stateless machines) m)
568
     )
569
    fmt (list_to_partial filtered_existencials);
570
    fprintf fmt "/*@@%a@,%a*/ {"
571
      (pp_acsl_instrs_assert false outputs self [] m.minstances m.mcalls vars) (m.mstep.step_instrs@instrs)
572
      (C_backend_spec.pp_assigns (List.map (fun x fmt-> Printers.pp_var_name fmt x) locals) stateless machines) m
573
    
574
    let print_step_code_postfix stateless fmt m =
575
      let inputs = m.mstep.step_inputs in
576
      let outputs = m.mstep.step_outputs in
577
      let locals = m.mstep.step_locals in
578
      let memory = m.mmemory in
579
      let vars = inputs@outputs@locals@memory in
580
      let mems = Machine_code.get_mems m machines in
581
      let self = if List.length mems == 0 then "" else mk_self m in
582
      Spec.SrcMod.print_step_code_postfix stateless fmt m;
583
      
584
      let filtered_existencials = (if fullExists then 
585
        let nonlocals = List.fold_left (fun l x-> match preprocess_acsl_instr m.mcalls outputs x with | Some (i, _) -> i::l | None -> l) [] m.mstep.step_instrs in
586
        List.filter (fun x-> not (List.mem x nonlocals)) else fun x -> x) locals
587
      in
588
      
589
      for i = 0 to List.length filtered_existencials + 2 do
590
        fprintf fmt "}"
591
      done
592
    
593
    let print_init_code_postfix fmt m = Spec.SrcMod.print_init_code_postfix fmt m
594
  end
595

    
596
  module MakefileMod =
597
  struct
598
    let other_targets fmt basename nodename dependencies = Spec.MakefileMod.other_targets fmt basename nodename dependencies
599
  end
600

    
601
  module MainMod =
602
  struct
603
    let print_while_prefix fmt m =
604
  (match m.mspec with
605
      | Some _ when getDepth m != 0 -> fprintf fmt "/*@@ loop invariant %a;*/@," (pp_acsl_fun_inv (getDepth m) m.mname.node_id "main_mem") (Some "")
606
      | _ -> ()
607
  );
608
  end
609

    
610
  module CoqMod =
611
  struct
612

    
613
    let repeat n fmt x =
614
        for i = 0 to n - 1 do
615
            fprintf fmt "%s" x
616
        done
617

    
618
    let pp_intro_hyp fmt k =
619
      fprintf fmt "(*nb: %i*)\nintros " k;
620
      repeat (k-1) fmt "[? ";
621
      fprintf fmt "?";
622
      repeat (k-1) fmt "]";
623
      fprintf fmt ".\n"
624

    
625
    let pp_choose nbcase fmt k =
626
      fprintf fmt "(*choose case %i/%i*)\n" (k+1) nbcase;
627
      repeat k fmt "right.\n";
628
      (if k != nbcase - 1 then fprintf fmt "left.\n")
629

    
630
    let pp_intros_exists fmt =
631
        fprintf fmt "repeat eapply ex_intro.\n"
632

    
633
    let pp_split fmt k =
634
      fprintf fmt "(*nb goals: %i(split one less)*)\n" k;
635
      repeat (k-1) fmt "split.\nFocus 2.\n"
636

    
637
    let pp_eassumption fmt k =
638
      repeat k fmt "eassumption.\n"
639

    
640

    
641
    let pp_apply_lem_init fmt k =
642
      fprintf fmt "eapply (Q_inv_init_%i_AltitudeControl).\n" k;
643
      let nbgoals = k+1+k+2 in
644
      for i = 0 to k-1 do
645
        fprintf fmt "Focus %i.\n" (nbgoals-i);
646
        fprintf fmt "eassumption.\n";
647
      done;
648
      for i = 1 to nbgoals-k do
649
        fprintf fmt "eassumption.\n";
650
      done
651

    
652
    let pp_apply_inv_spec fmt name =
653
      fprintf fmt "eapply Q_inv_spec_%s.\n" name;
654
      fprintf fmt "Focus 5.\n";
655
      for i = 1 to 5 do
656
        fprintf fmt "eassumption.\n"
657
      done
658

    
659
    let pp_case nbgoals1 nbgoals2 nbgoals3 nbintro nbcase case_hyp case_goal fmt name =
660
      let nbgoals = nbgoals1 + nbgoals2 + nbgoals3 in
661
      if case_hyp != nbcase - 1 then (
662
        fprintf fmt "intros h.\n";
663
        fprintf fmt "elim h;clear h.\n"
664
      );
665
      pp_intro_hyp fmt nbintro;
666
      pp_choose nbcase fmt case_goal;
667
      pp_intros_exists fmt;
668
      pp_split fmt nbgoals;
669
      pp_eassumption fmt nbgoals3;
670
      (
671
      if case_hyp == nbcase -2 then
672
        for i = 0 to case_goal - 1 do
673
          pp_apply_lem_init fmt (case_goal - i)
674
        done
675
      else (if case_hyp == nbcase -1 then
676
        (pp_apply_inv_spec fmt name;
677
        for i = 1 to nbgoals2 - 1 do
678
          fprintf fmt "eassumption.\n"
679
        done)
680
      else
681
        ())
682
      );
683
      pp_eassumption fmt nbgoals1
684
    
685
    let pp_code_inv_inv m fmt name =
686
      let inputs = m.mstep.step_inputs in
687
      let outputs = m.mstep.step_outputs in
688
      let locals = m.mstep.step_locals in
689
      let memory = m.mmemory in
690
      let vars = inputs@outputs@locals@memory in
691
      let depth = getDepth m in
692
      let nbcase = depth + 1 in
693
      let spec = (Spec.get_spec m.mname) in
694
      fprintf fmt "intros.\n";
695
      fprintf fmt "generalize H2.\n";
696
      fprintf fmt "unfold P_inv_%s.\n" name;
697
      let computeAnd k = (
698
        1*k + (*mems*)
699
        (List.length spec.m_requires)*k + (*pre*)
700
        (if k == nbcase -1 then 0 else 1), (*init*)
701
        (if k == nbcase -1 then (List.length spec.m_ensures) else 0)*k, (*post*)
702
        1*k (*trans*)
703
      ) in
704
      for case_hyp = 0 to nbcase - 1 do
705
        let case_goal = min (case_hyp+1) (nbcase -1) in
706
        let (nbgoals1, nbgoals2, nbgoals3) = computeAnd case_goal in
707
        let (nbhyp1, nbhyp2, nbhyp3) = computeAnd case_hyp in
708
        let vars = ((List.length inputs) + (List.length outputs) + 1)*case_hyp in
709
        let nbintro = vars + nbhyp1 + nbhyp2 + nbhyp3 in
710
        fprintf fmt "(*Case %i/%i -> %i/%i*)\n" (case_hyp+1) nbcase (case_goal+1) nbcase;
711
        fprintf fmt "(*nb var and hyps in case hyp: %i+%i+%i+%i*)\n" vars nbhyp1 nbhyp2 nbhyp3;
712
        fprintf fmt "(*nb goals in case goal : %i+%i+%i*)\n" nbgoals1 nbgoals2 nbgoals3;
713
        pp_case nbgoals1 nbgoals2 nbgoals3 nbintro  nbcase case_hyp case_goal fmt name
714
      done
715

    
716
    let pp_code_inv fmt name =
717
      fprintf fmt "intros.\n";
718
      fprintf fmt "eapply Q_inv_inv_%s.\n" name;
719
      fprintf fmt "Focus 4.\n";
720
      fprintf fmt "eassumption.\n";
721
      fprintf fmt "eassumption.\n";
722
      fprintf fmt "eassumption.\n";
723
      fprintf fmt "eassumption.\n"
724

    
725
    (*
726
      fprintf fmt "intros;\n";
727
      fprintf fmt "eapply Q_inv_inv_%s;" name;
728
      fprintf fmt "match goal with | |- context [P_Ctrans_%s]=> eassumption | _ => idtac end;\n" name;
729
      fprintf fmt "intuition;\n";
730
      fprintf fmt "(match goal with";
731
      fprintf fmt "  | |- context [if ?t then _ else _] => destruct t\n";
732
      fprintf fmt "  | _ => idtac\n";
733
      fprintf fmt "  end);hnf;try omega;intuition.\n"
734
    *)
735

    
736
    let pp_coq_goal name goalname code fmt =
737
        fprintf fmt "Goal %t.\nProof.\n%aQed.\n\n" (fun fmt-> fprintf fmt goalname name) code name
738

    
739
    let pp_coq stateless fmt m =
740
      match m.mspec with
741
        | Some _ ->
742
          let name = m.mname.node_id in
743
          if name <> arrow_id then (
744
            pp_coq_goal name "typed_%s_step_post" pp_code_inv fmt;
745
            pp_coq_goal name "typed_ref_%s_step_post" pp_code_inv fmt;
746
            pp_coq_goal name "typed_lemma_inv_inv_%s" (pp_code_inv_inv m) fmt
747
          )
748
        | _ -> ()
749

    
750
end
751

    
752
end
753
(* Local Variables: *)
754
(* compile-command:"make -C ../../.." *)
755
(* End: *)
(7-7/9)