Project

General

Profile

Download (31.3 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)?1:0)" | _ -> 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
(* Print a transition call/decl in acsl *)
220
let pp_acsl_fun_trans infos pre name inputs outputs suffix flag_output self flag_mem locals fmt existential =
221
  let (locals, existential) = (*([], match existential with None -> None | Some x -> Some []) in*)
222
  match infos with
223
    | None -> (locals, existential)
224
    | Some (instrs, calls) ->
225
      let nonlocals = List.fold_left (fun l x-> match preprocess_acsl_instr calls outputs x with | Some (i, _) -> i::l | None -> l) [] instrs in
226
      (
227
        (if fullExists then List.filter (fun x-> not (List.mem x nonlocals)) else fun x -> x) locals,
228
        match existential with None -> None | Some existential -> Some ((if fullExists then List.filter (fun x-> not (List.mem x nonlocals)) else fun x -> x) existential)
229
      )
230
  in
231
  let mems = function 1 -> "Pre" | 2 -> "Here" | _ -> assert false in
232
  let pp_self_read =
233
    if flag_mem then fun i fmt-> fprintf fmt "\\at(*%s, %s)" self (mems i)
234
    else fun i fmt-> fprintf fmt "%s%i" self (match suffix with None -> i | Some s -> s+i-1)
235
  in
236
  let (pp_var, pp_self) =
237
    match existential with
238
      | None    -> (pp_acsl_var_decl, (fun i fmt-> fprintf fmt "%a %s%i" pp_machine_memtype_name name self i))
239
      | Some ex -> (if List.length ex != 0 then fprintf fmt "\\exists %a;@," (Utils.fprintf_list ~sep:";@,\\exists " pp_acsl_var_decl) ex);
240
                   (pp_acsl_var_read (if flag_output then outputs else []), pp_self_read)
241
  in
242
  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
243
    (pp_acsl_fun (pre^"trans_"^name)) fmt
244
    ((pp_vars (inputs@outputs))@(if not (self = "") then [pp_self 1;pp_self 2] else [])@(pp_vars locals))
245

    
246
(* Print an invariant call/decl in acsl *)
247
let pp_acsl_fun_inv depth name self fmt mem =
248
  let arg = fun fmt-> (match mem with
249
    | None -> fprintf fmt "%a %s%i" pp_machine_memtype_name name self depth
250
    | Some "" -> fprintf fmt "%s" self
251
    | Some "Here" -> fprintf fmt "*%s" self
252
    | Some m -> fprintf fmt "\\at(*%s, %s)" self m)
253
  in
254
  pp_acsl_fun ("inv_"^name) fmt [arg]
255

    
256
(* Print an invariant call/decl in acsl *)
257
let pp_acsl_inv depth name inputs outputs self fmt spec =
258
  let rec iter base x = function
259
    | i when i = base-1 -> []
260
    | i -> (i, x)::(iter base x (i-1))
261
  in
262
  let rec iterList base = function
263
    | []   -> []
264
    | t::q -> (iter base t depth)@(iterList base q)
265
  in
266
  let trans_pred fmt i =
267
    fprintf fmt "%a" (pp_acsl_fun_trans  None "C" name inputs outputs (Some i) false self false []) (Some [])
268
  in
269
  let pp_eexpr_expr self i j fmt ee = 
270
    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
271
  in
272
  let spec_pred cor preds fmt i =
273
    let j = if cor then i + 1 else i in
274
    fprintf fmt "(%a)" (Utils.fprintf_list ~sep:"&&@," (pp_eexpr_expr self i j)) preds
275
  in
276
  let aux fmt base =
277
    let selfs = iter base self (depth-1) in
278
    let ios = iterList (base + 1) (inputs@outputs) in
279
    (if List.length selfs == 0 && List.length ios == 0 then 
280
      fprintf fmt "(%a%t%a%t%t)"
281
     else
282
      fprintf fmt "(\\exists %a%t%a;@,%a%t%a%t%t)"
283
        (Utils.fprintf_list ~sep:", "   (fun fmt (i, x)-> fprintf fmt "%a %s%i" pp_machine_memtype_name name self i)) selfs
284
        (Utils.pp_final_char_if_non_empty ", " (iter base self (depth-1)))
285
        (Utils.fprintf_list ~sep:", "   (fun fmt (i, x)-> fprintf fmt "%a%i" pp_acsl_var_decl x i)) ios
286
    )
287
      (Utils.fprintf_list ~sep:"&&@," (fun fmt (i, f)-> fprintf fmt "%a" f i)) (iter base trans_pred (depth-1))
288
      (Utils.pp_final_char_if_non_empty "&&@," (iter base trans_pred (depth-1))) 
289
      (Utils.fprintf_list ~sep:"&&@," (fun fmt (i, f)-> fprintf fmt "%a" f i)) (iter base (spec_pred true spec.m_requires) (depth-1))
290
      (Utils.pp_final_char_if_non_empty "&&@," (iter base (spec_pred true spec.m_requires) (depth-1))) 
291
      (fun fmt->
292
        if base == 0 then
293
          Utils.fprintf_list ~sep:"&&@," (fun fmt (i, f)-> fprintf fmt "%a" f i) fmt (iter (base+1) (spec_pred false spec.m_ensures) depth)
294
        else
295
          pp_acsl_fun_init name (self^(string_of_int base)) "" fmt (Some "")
296
      )
297
  in
298
  Utils.fprintf_list ~sep:"||@," (fun fmt (i, f)-> fprintf fmt "%a" f i) fmt (iter 0 aux depth)
299

    
300
(* Print the invariant lemma *)
301
let pp_acsl_lem_inv depth name inputs outputs self fmt spec =
302
  let pp_eexpr_expr self j fmt ee =
303
    fprintf fmt "spec_%i(%a, %s%i)" ee.muid (Utils.fprintf_list ~sep:", " (pp_acsl_var_read [])) ee.mmstep_logic.step_inputs self j
304
  in
305
  fprintf fmt "\\forall %a %s1, %s2, %a;@,%a==>@,%a==>@,%a%t%a"
306
    pp_machine_memtype_name name self self
307
    (Utils.fprintf_list ~sep:", " pp_acsl_var_decl) (inputs@outputs)
308
    (pp_acsl_fun_inv depth name (self^"1")) (Some "")
309
    (pp_acsl_fun_trans None "C" name inputs outputs None false self false []) (Some [])
310
    (Utils.fprintf_list ~sep:"==>@," (pp_eexpr_expr self 1)) spec.m_requires
311
    (Utils.pp_final_char_if_non_empty "==>@," spec.m_requires)
312
    (pp_acsl_fun_inv depth name (self^"2")) (Some "")
313

    
314
(* Print lemma init *)
315
let pp_acsl_lem_init k depth name inputs outputs self fmt spec =
316
  let rec iter base x = function
317
    | i when i = base-1 -> []
318
    | i -> (i, x)::(iter base x (i-1))
319
  in
320
  let rec iterList base = function
321
    | []   -> []
322
    | t::q -> (iter base t depth)@(iterList base q)
323
  in
324
  let trans_pred fmt i =
325
    fprintf fmt "%a" (pp_acsl_fun_trans  None "C" name inputs outputs (Some i) false self false []) (Some [])
326
  in
327
  let spec_pred fmt i =
328
    let pp_eexpr_expr self j fmt ee = 
329
      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
330
    in
331
    fprintf fmt "%a%t(%a)"
332
    (Utils.fprintf_list ~sep:"==>@," ((fun fmt (w, x)-> fprintf fmt "%a"
333
      (Utils.fprintf_list ~sep:"==>@," (pp_eexpr_expr self (w))) spec.m_requires
334
    ))) (iter k None (depth -1))
335
    (Utils.pp_final_char_if_non_empty "==>@," spec.m_requires)
336
    (Utils.fprintf_list ~sep:"&&@," (pp_eexpr_expr self (i))) spec.m_ensures
337
  in
338
  let aux fmt base =
339
    let selfs = iter base self (depth) in
340
    let ios = iterList (base + 1) (inputs@outputs) in
341
    (if List.length selfs == 0 && List.length ios == 0 then 
342
      fprintf fmt "(%a%t%t)"
343
     else
344
      fprintf fmt "\\forall %a%t%a;@,%a%t%t"
345
        (Utils.fprintf_list ~sep:", "   (fun fmt (i, x)-> fprintf fmt "%a %s%i" pp_machine_memtype_name name self i)) selfs
346
        (Utils.pp_final_char_if_non_empty ", " (iter base self (depth-1)))
347
        (Utils.fprintf_list ~sep:", "   (fun fmt (i, x)-> fprintf fmt "%a%i" pp_acsl_var_decl x i)) ios
348
    )
349
      (Utils.fprintf_list ~sep:"==>@," (fun fmt (i, f)-> fprintf fmt "%a" f i)) (iter base trans_pred (depth-1))
350
      (Utils.pp_final_char_if_non_empty "==>@," (iter base trans_pred (depth-1))) 
351
      (fun fmt->
352
          pp_acsl_fun_init name (self^(string_of_int base)) "" fmt (Some "")
353
      )
354
  in
355
  fprintf fmt "%a ==> %a" aux k spec_pred depth
356

    
357
(* Print the spec lemma *)
358
let pp_acsl_lem_spec depth name inputs outputs self fmt spec =
359
  let pp_eexpr_expr self j fmt ee =
360
    fprintf fmt "spec_%i(%a, %s%i)" ee.muid (Utils.fprintf_list ~sep:", " (pp_acsl_var_read [])) ee.mmstep_logic.step_inputs self j
361
  in
362
  fprintf fmt "\\forall %a %s1, %s2, %a;@,%a==>@,%a==>@,%a%t%a"
363
    pp_machine_memtype_name name self self
364
    (Utils.fprintf_list ~sep:", " pp_acsl_var_decl) (inputs@outputs)
365
    (pp_acsl_fun_inv depth name (self^"1")) (Some "")
366
    (pp_acsl_fun_trans None "C" name inputs outputs None false self false []) (Some [])
367
    (Utils.fprintf_list ~sep:"==>@," (pp_eexpr_expr self 1)) spec.m_requires
368
    (Utils.pp_final_char_if_non_empty "==>@," spec.m_requires)
369
    (Utils.fprintf_list ~sep:"&&@," (pp_eexpr_expr self 2)) spec.m_ensures
370

    
371
let getDepth m =
372
  try (
373
    match (List.assoc ["k"] (List.flatten (List.map (fun x-> x.annots) m.mannot))).eexpr_qfexpr.expr_desc with
374
      | (Expr_const (Const_int k)) -> k
375
      | _ -> 0
376
  ) with Not_found -> 0
377

    
378
(* Get the instructions from acsl spec effect *)
379
let get_instrs_effect spec =
380
  let effects = spec.m_requires@spec.m_ensures@
381
    (List.fold_left 
382
       (fun accu (_,assumes, ensures) -> assumes@ensures@accu) 
383
      [] spec.m_behaviors)
384
  in
385
  let effects = List.filter (fun ee -> ee.mmstep_effects.step_instrs <> []) effects in
386
  List.flatten (List.map (fun e -> e.mmstep_effects.step_instrs) effects)
387

    
388
let get_instrs_effect_init spec =
389
  let effects = spec.m_requires@spec.m_ensures@
390
    (List.fold_left 
391
       (fun accu (_,assumes, ensures) -> assumes@ensures@accu) 
392
       [] spec.m_behaviors)
393
  in
394
  
395
  let effects = List.filter (fun ee -> ee.mminit <> []) effects in
396
  List.flatten (List.map (fun e -> e.mminit) effects)
397

    
398
module Make = 
399
  functor (SpecArg: SPECARG) -> 
400
struct
401
  
402
  open SpecArg
403

    
404
  module Spec = Make(SpecArg)
405

    
406
  let init m = Spec.init m
407

    
408
  module HdrMod = struct
409

    
410
    (* Print all the proof stuff *)
411
    let pp_acsl_def_trans stateless fmt m =
412
      let name = m.mname.node_id in
413
      let inputs = m.mstep.step_inputs in
414
      let outputs = m.mstep.step_outputs in
415
      let locals = m.mstep.step_locals in
416
      let memory = m.mmemory in
417
      let vars = inputs@outputs@locals@memory in
418
      let depth = getDepth m in
419
      let instrs = match m.mspec with None -> [] | Some spec -> get_instrs_effect (Spec.get_spec m.mname) in
420
      let instrs_init =  match m.mspec with None -> [] | Some spec -> get_instrs_effect_init (Spec.get_spec m.mname) in
421
      let induction = (not stateless) && (getDepth m != 0) in
422
      if m.mname.node_id <> arrow_id then (
423
        let self = if stateless then "" else mk_self m in
424
        fprintf fmt "/*@@ @[<v 3>predicate %a =@;%a;@]@;*/@."
425
          (pp_acsl_fun_trans (Some (m.mstep.step_instrs, m.mcalls)) "" name inputs outputs None false self false locals) None
426
            (pp_acsl_instrs false outputs self [] m.minstances m.mcalls vars) (m.mstep.step_instrs@instrs);
427
        fprintf fmt "/*@@ @[<v 3>predicate %a =@;%a;@]@;*/@."
428
          (pp_acsl_fun_trans None "C" name inputs outputs None false self false []) None
429
            (pp_acsl_fun_trans (Some (m.mstep.step_instrs, m.mcalls)) "" name inputs outputs None false self false locals) (Some locals);
430
        (if not stateless then fprintf fmt "/*@@ @[<v 3>predicate %a =@;%a;@]@;*/@."
431
          (pp_acsl_fun_init name self "") None
432
            (pp_acsl_instrs true [] self [] m.minstances m.mcalls vars) (m.minit@instrs_init));
433
        if induction then (
434
        match m.mspec with None -> () | Some spec -> (
435
          let spec = (Spec.get_spec m.mname) in
436
          fprintf fmt "/*@@ @[<v 3>predicate %a =@;%a;@]@;*/@." (pp_acsl_fun_inv depth name self) None (pp_acsl_inv depth name inputs outputs self) spec;
437
          for i = 0 to depth-1 do
438
            fprintf fmt "/*@@ @[<v 3>lemma inv_init_%i_%s : @;%a;@]@;*/@." (depth-i) name (pp_acsl_lem_init i depth name inputs outputs self) spec;
439
          done;
440
          fprintf fmt "/*@@ @[<v 3>lemma inv_spec_%s : @;%a;@]@;*/@." name (pp_acsl_lem_spec depth name inputs outputs self) spec;
441
          fprintf fmt "/*@@ @[<v 3>lemma inv_inv_%s : @;%a;@]@;*/@." name (pp_acsl_lem_inv depth name inputs outputs self) spec
442
        )
443
      ))
444
    let _print_machine_decl_step_fun_prefix stateless fmt m =
445
      let self = mk_self m in
446
      let induction = (not stateless) && (getDepth m != 0) in
447
      let pre_inv = fun fmt -> fprintf fmt "requires %a;@," (pp_acsl_fun_inv (getDepth m) m.mname.node_id self) (Some "Here") in
448
      let post_inv = fun fmt -> fprintf fmt "ensures %a;@," (pp_acsl_fun_inv (getDepth m) m.mname.node_id self) (Some "Here") in
449
        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
450
      let pre = match m.mspec with
451
        | Some _ when induction -> pre_inv
452
        | _ -> fun fmt -> ()
453
      in
454
      let post = match m.mspec with
455
        | Some _ when induction -> fun fmt -> fprintf fmt "%t%t" post_inv post_trans
456
        | _ -> post_trans
457
      in
458
      Spec.HdrMod._print_machine_decl_step_fun_prefix stateless pre post fmt m
459

    
460
    let has_spec_mem m = Spec.HdrMod.has_spec_mem m
461
    let pp_registers_struct fmt m = Spec.HdrMod.pp_registers_struct fmt m
462
    let print_machine_decl_prefix fmt m =
463
        let mems = Machine_code.get_mems m machines in
464
        fprintf fmt "%a%a"
465
          Spec.HdrMod.print_machine_decl_prefix m
466
          (pp_acsl_def_trans (List.length mems == 0)) m
467
    let print_machine_decl_step_fun_prefix fmt m = _print_machine_decl_step_fun_prefix false fmt m
468
    
469
    let print_machine_decl_init_fun_prefix fmt m =
470
      let self = mk_self m in
471
      let post fmt = 
472
          fprintf fmt "ensures %a;@." (pp_acsl_fun_init m.mname.node_id self "") (Some "Here");
473
        match m.mspec with
474
        | Some _ when getDepth m != 0 ->
475
            fprintf fmt "ensures %a;@." (pp_acsl_fun_inv (getDepth m) m.mname.node_id self) (Some "Here")
476
        | _ -> ()
477
          
478
      in
479
      Spec.HdrMod._print_machine_decl_init_fun_prefix (fun fmt-> ()) post fmt m
480
    
481
    let print_machine_decl_stateless_fun_prefix fmt m = _print_machine_decl_step_fun_prefix true fmt m
482
    
483
    let print_global_decl fmt = fprintf fmt "/*@@ @[<v 3>lemma missing: \\forall _Bool x; (x != 0) <==> (((int) x) != 0);*/@."
484
  end
485

    
486
  module SrcMod =
487
  struct
488
    let print_step_code_prefix stateless fmt m =
489
      let inputs = m.mstep.step_inputs in
490
      let outputs = m.mstep.step_outputs in
491
      let locals = m.mstep.step_locals in
492
      let mems = Machine_code.get_mems m machines in
493
      let self = if List.length mems == 0 then "" else mk_self m in
494
      fprintf fmt "/*@@ensures %a;@,%a*/@,{@," 
495
        (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 [])
496
        (C_backend_spec.pp_assigns [] stateless machines) m
497
    let print_step_code_midfix stateless fmt m =
498
      let inputs = m.mstep.step_inputs in
499
      let outputs = m.mstep.step_outputs in
500
      let locals = m.mstep.step_locals in
501
      let mems = Machine_code.get_mems m machines in
502
      let self = if List.length mems == 0 then "" else mk_self m in
503
      let instrs = match m.mspec with None -> [] | Some spec -> get_instrs_effect (Spec.get_spec m.mname) in
504
      let memory = m.mmemory in
505
      let vars = inputs@outputs@locals@memory in
506
      let filtered_existencials = (if fullExists then 
507
        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
508
        List.filter (fun x-> not (List.mem x nonlocals))else fun x -> x) locals
509
      in
510
      Format.fprintf fmt "@,/* Asserting trans predicate: locals are [%a] */@,"
511
        (fprintf_list ~sep:", " Printers.pp_var) filtered_existencials;
512
      (Utils.fprintf_list ~sep:"@," 
513
        (fun fmt x -> 
514
          fprintf fmt "/*@@ensures %a;@,%a*/@,{@," 
515
        (pp_acsl_fun_trans 
516
           (Some (m.mstep.step_instrs, m.mcalls)) 
517
           "" (* no predicate prefix *)
518
           m.mname.node_id
519
           inputs 
520
           outputs 
521
           None 
522
           true
523
           self
524
           true
525
           locals
526
        ) 
527
        (Some x) 
528
        (C_backend_spec.pp_assigns (List.map (fun x fmt-> Printers.pp_var_name fmt x) locals) stateless machines) m)
529
     )
530
    fmt (list_to_partial filtered_existencials);
531
    fprintf fmt "/*@@%a@,%a*/ {"
532
      (pp_acsl_instrs_assert false outputs self [] m.minstances m.mcalls vars) (m.mstep.step_instrs@instrs)
533
      (C_backend_spec.pp_assigns (List.map (fun x fmt-> Printers.pp_var_name fmt x) locals) stateless machines) m
534
    
535
    let print_step_code_postfix stateless fmt m =
536
      let inputs = m.mstep.step_inputs in
537
      let outputs = m.mstep.step_outputs in
538
      let locals = m.mstep.step_locals in
539
      let memory = m.mmemory in
540
      let vars = inputs@outputs@locals@memory in
541
      let mems = Machine_code.get_mems m machines in
542
      let self = if List.length mems == 0 then "" else mk_self m in
543
      Spec.SrcMod.print_step_code_postfix stateless fmt m;
544
      
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
      
550
      for i = 0 to List.length filtered_existencials + 2 do
551
        fprintf fmt "}"
552
      done
553
    
554
    let print_init_code_postfix fmt m = Spec.SrcMod.print_init_code_postfix fmt m
555
  end
556

    
557
  module MakefileMod =
558
  struct
559
    let other_targets fmt basename nodename dependencies = Spec.MakefileMod.other_targets fmt basename nodename dependencies
560
  end
561

    
562
  module MainMod =
563
  struct
564
    let print_while_prefix fmt m =
565
  (match m.mspec with
566
      | Some _ when getDepth m != 0 -> fprintf fmt "/*@@ loop invariant %a;*/@," (pp_acsl_fun_inv (getDepth m) m.mname.node_id "main_mem") (Some "")
567
      | _ -> ()
568
  );
569
  end
570

    
571
  module CoqMod =
572
  struct
573

    
574
    let repeat n fmt x =
575
        for i = 0 to n - 1 do
576
            fprintf fmt "%s" x
577
        done
578

    
579
    let pp_intro_hyp fmt k =
580
      fprintf fmt "(*nb: %i*)\nintros " k;
581
      repeat (k-1) fmt "[? ";
582
      fprintf fmt "?";
583
      repeat (k-1) fmt "]";
584
      fprintf fmt ".\n"
585

    
586
    let pp_choose nbcase fmt k =
587
      fprintf fmt "(*choose case %i/%i*)\n" (k+1) nbcase;
588
      repeat k fmt "right.\n";
589
      (if k != nbcase - 1 then fprintf fmt "left.\n")
590

    
591
    let pp_intros_exists fmt =
592
        fprintf fmt "repeat eapply ex_intro.\n"
593

    
594
    let pp_split fmt k =
595
      fprintf fmt "(*nb goals: %i(split one less)*)\n" k;
596
      repeat (k-1) fmt "split.\nFocus 2.\n"
597

    
598
    let pp_eassumption fmt k =
599
      repeat k fmt "eassumption.\n"
600

    
601

    
602
    let pp_apply_lem_init fmt k =
603
      fprintf fmt "eapply (Q_inv_init_%i_AltitudeControl).\n" k;
604
      let nbgoals = k+1+k+2 in
605
      for i = 0 to k-1 do
606
        fprintf fmt "Focus %i.\n" (nbgoals-i);
607
        fprintf fmt "eassumption.\n";
608
      done;
609
      for i = 1 to nbgoals-k do
610
        fprintf fmt "eassumption.\n";
611
      done
612

    
613
    let pp_apply_inv_spec fmt name =
614
      fprintf fmt "eapply Q_inv_spec_%s.\n" name;
615
      fprintf fmt "Focus 5.\n";
616
      for i = 1 to 5 do
617
        fprintf fmt "eassumption.\n"
618
      done
619

    
620
    let pp_case nbgoals1 nbgoals2 nbgoals3 nbintro nbcase case_hyp case_goal fmt name =
621
      let nbgoals = nbgoals1 + nbgoals2 + nbgoals3 in
622
      if case_hyp != nbcase - 1 then (
623
        fprintf fmt "intros h.\n";
624
        fprintf fmt "elim h;clear h.\n"
625
      );
626
      pp_intro_hyp fmt nbintro;
627
      pp_choose nbcase fmt case_goal;
628
      pp_intros_exists fmt;
629
      pp_split fmt nbgoals;
630
      pp_eassumption fmt nbgoals3;
631
      (
632
      if case_hyp == nbcase -2 then
633
        for i = 0 to case_goal - 1 do
634
          pp_apply_lem_init fmt (case_goal - i)
635
        done
636
      else (if case_hyp == nbcase -1 then
637
        (pp_apply_inv_spec fmt name;
638
        for i = 1 to nbgoals2 - 1 do
639
          fprintf fmt "eassumption.\n"
640
        done)
641
      else
642
        ())
643
      );
644
      pp_eassumption fmt nbgoals1
645
    
646
    let pp_code_inv_inv m fmt name =
647
      let inputs = m.mstep.step_inputs in
648
      let outputs = m.mstep.step_outputs in
649
      let locals = m.mstep.step_locals in
650
      let memory = m.mmemory in
651
      let vars = inputs@outputs@locals@memory in
652
      let depth = getDepth m in
653
      let nbcase = depth + 1 in
654
      let spec = (Spec.get_spec m.mname) in
655
      fprintf fmt "intros.\n";
656
      fprintf fmt "generalize H2.\n";
657
      fprintf fmt "unfold P_inv_%s.\n" name;
658
      let computeAnd k = (
659
        1*k + (*mems*)
660
        (List.length spec.m_requires)*k + (*pre*)
661
        (if k == nbcase -1 then 0 else 1), (*init*)
662
        (if k == nbcase -1 then (List.length spec.m_ensures) else 0)*k, (*post*)
663
        1*k (*trans*)
664
      ) in
665
      for case_hyp = 0 to nbcase - 1 do
666
        let case_goal = min (case_hyp+1) (nbcase -1) in
667
        let (nbgoals1, nbgoals2, nbgoals3) = computeAnd case_goal in
668
        let (nbhyp1, nbhyp2, nbhyp3) = computeAnd case_hyp in
669
        let vars = ((List.length inputs) + (List.length outputs) + 1)*case_hyp in
670
        let nbintro = vars + nbhyp1 + nbhyp2 + nbhyp3 in
671
        fprintf fmt "(*Case %i/%i -> %i/%i*)\n" (case_hyp+1) nbcase (case_goal+1) nbcase;
672
        fprintf fmt "(*nb var and hyps in case hyp: %i+%i+%i+%i*)\n" vars nbhyp1 nbhyp2 nbhyp3;
673
        fprintf fmt "(*nb goals in case goal : %i+%i+%i*)\n" nbgoals1 nbgoals2 nbgoals3;
674
        pp_case nbgoals1 nbgoals2 nbgoals3 nbintro  nbcase case_hyp case_goal fmt name
675
      done
676

    
677
    let pp_code_inv fmt name =
678
      fprintf fmt "intros.\n";
679
      fprintf fmt "eapply Q_inv_inv_%s.\n" name;
680
      fprintf fmt "Focus 4.\n";
681
      fprintf fmt "eassumption.\n";
682
      fprintf fmt "eassumption.\n";
683
      fprintf fmt "eassumption.\n";
684
      fprintf fmt "eassumption.\n"
685

    
686
    (*
687
      fprintf fmt "intros;\n";
688
      fprintf fmt "eapply Q_inv_inv_%s;" name;
689
      fprintf fmt "match goal with | |- context [P_Ctrans_%s]=> eassumption | _ => idtac end;\n" name;
690
      fprintf fmt "intuition;\n";
691
      fprintf fmt "(match goal with";
692
      fprintf fmt "  | |- context [if ?t then _ else _] => destruct t\n";
693
      fprintf fmt "  | _ => idtac\n";
694
      fprintf fmt "  end);hnf;try omega;intuition.\n"
695
    *)
696

    
697
    let pp_coq_goal name goalname code fmt =
698
        fprintf fmt "Goal %t.\nProof.\n%aQed.\n\n" (fun fmt-> fprintf fmt goalname name) code name
699

    
700
    let pp_coq stateless fmt m =
701
      match m.mspec with
702
        | Some _ ->
703
          let name = m.mname.node_id in
704
          if name <> arrow_id then (
705
            pp_coq_goal name "typed_%s_step_post" pp_code_inv fmt;
706
            pp_coq_goal name "typed_ref_%s_step_post" pp_code_inv fmt;
707
            pp_coq_goal name "typed_lemma_inv_inv_%s" (pp_code_inv_inv m) fmt
708
          )
709
        | _ -> ()
710

    
711
end
712

    
713
end
714
(* Local Variables: *)
715
(* compile-command:"make -C ../../.." *)
716
(* End: *)
(7-7/9)