Project

General

Profile

Download (58.2 KB) Statistics
| Branch: | Tag: | Revision:
1
(********************************************************************)
2
(*                                                                  *)
3
(*  The LustreC compiler toolset   /  The LustreC Development Team  *)
4
(*  Copyright 2012 -    --   ONERA - CNRS - INPT                    *)
5
(*                                                                  *)
6
(*  LustreC is free software, distributed WITHOUT ANY WARRANTY      *)
7
(*  under the terms of the GNU Lesser General Public License        *)
8
(*  version 2.1.                                                    *)
9
(*                                                                  *)
10
(********************************************************************)
11
open Utils
12
open Format
13
open Lustre_types
14
open Machine_code_types
15
open C_backend_common
16
open Corelang
17
open Spec_types
18
open Machine_code_common
19
module Mpfr = Lustrec_mpfr
20

    
21
(**************************************************************************)
22
(*     Printing spec for c *)
23

    
24
(**************************************************************************)
25

    
26
let pp_acsl_basic_type_desc t_desc =
27
  if Types.is_bool_type t_desc then
28
    (* if !Options.cpp then "bool" else "_Bool" *)
29
    "_Bool"
30
  else if Types.is_int_type t_desc then
31
    (* !Options.int_type *)
32
    if t_desc.tid = -1 then "int" else "integer"
33
  else if Types.is_real_type t_desc then
34
    if !Options.mpfr then Mpfr.mpfr_t else !Options.real_type
35
  else assert false
36
(* Not a basic C type. Do not handle arrays or pointers *)
37

    
38
let pp_acsl pp fmt = fprintf fmt "@[<v>/*%@ @[<v>%a@]@,*/@]" pp
39

    
40
let pp_acsl_cut pp fmt = fprintf fmt "%a@," (pp_acsl pp)
41

    
42
let pp_acsl_line pp fmt = fprintf fmt "//%@ @[<h>%a@]" pp
43

    
44
let pp_acsl_line' ?(ghost = false) pp fmt x =
45
  let op = if ghost then "" else "*" in
46
  let cl = if ghost then "@" else "*" in
47
  fprintf fmt "/%s%@ @[<h>%a@] %s/" op pp x cl
48

    
49
let pp_acsl_line'_cut pp fmt = fprintf fmt "%a@," (pp_acsl_line' pp)
50

    
51
let pp_requires pp fmt = fprintf fmt "requires %a;" pp
52

    
53
let pp_ensures pp fmt = fprintf fmt "ensures %a;" pp
54

    
55
let pp_assumes pp fmt = fprintf fmt "assumes %a;" pp
56

    
57
let pp_terminates pp fmt = fprintf fmt "terminates %a;" pp
58

    
59
let pp_assigns pp =
60
  pp_comma_list
61
    ~pp_prologue:(fun fmt () -> pp_print_string fmt "assigns ")
62
    ~pp_epilogue:pp_print_semicolon'
63
    pp
64

    
65
let pp_ghost pp fmt = fprintf fmt "ghost %a" pp
66

    
67
let pp_assert pp fmt = fprintf fmt "assert %a;" pp
68

    
69
let pp_loop_invariant pp fmt = fprintf fmt "loop invariant %a;" pp
70

    
71
let pp_mem_valid pp_var fmt (name, var) =
72
  fprintf fmt "%s_valid(%a)" name pp_var var
73

    
74
let pp_mem_valid' = pp_mem_valid pp_print_string
75

    
76
let pp_ref pp fmt = fprintf fmt "&%a" pp
77

    
78
let pp_ref' = pp_ref pp_print_string
79

    
80
let pp_indirect pp_ptr pp_field fmt (ptr, field) =
81
  fprintf fmt "%a->%a" pp_ptr ptr pp_field field
82

    
83
let pp_indirect' = pp_indirect pp_print_string pp_print_string
84

    
85
let pp_access pp_stru pp_field fmt (stru, field) =
86
  fprintf fmt "%a.%a" pp_stru stru pp_field field
87

    
88
let pp_access' = pp_access pp_print_string pp_print_string
89

    
90
let pp_var_decl fmt v = pp_print_string fmt v.var_id
91

    
92
let pp_true fmt () = pp_print_string fmt "\\true"
93

    
94
let pp_cast pp_ty pp fmt (ty, x) = fprintf fmt "(%a) %a" pp_ty ty pp x
95

    
96
let pp_bool_cast pp fmt x = pp_cast pp_print_string pp fmt ("_Bool", x)
97

    
98
let pp_double_cast pp fmt x = pp_cast pp_print_string pp fmt ("double", x)
99

    
100
let pp_true_c_bool fmt () = pp_bool_cast pp_print_string fmt "1"
101

    
102
let pp_false fmt () = pp_print_string fmt "\\false"
103

    
104
let pp_nothing fmt () = pp_print_string fmt "\\nothing"
105

    
106
let pp_null fmt () = pp_print_string fmt "\\null"
107

    
108
let pp_stdout fmt () = pp_print_string fmt "stdout"
109

    
110
let pp_at pp_v fmt (v, l) = fprintf fmt "\\at(%a, %s)" pp_v v l
111

    
112
let pp_at_pre pp_v fmt v = pp_at pp_v fmt (v, "Pre")
113

    
114
let find_machine f = List.find (fun m -> m.mname.node_id = f)
115

    
116
let instances machines m =
117
  let rec aux m =
118
    List.(fold_left (fun insts (inst, (td, _)) ->
119
        let mems, insts' =
120
          try
121
            let m' = find_machine (node_name td) machines in
122
            m'.mmemory, aux m'
123
          with Not_found ->
124
            if Arrow.td_is_arrow td then arrow_machine.mmemory, [[]] else assert false
125
        in
126
        insts @ map (cons (inst, (td, mems))) insts') [[]] m.minstances)
127
  in
128
  match aux m with
129
  | [] :: l -> l
130
  | l -> l
131

    
132
let pp_instance ?(indirect = true) ?pp_epilogue fmt =
133
    pp_print_list
134
      ~pp_sep:(fun fmt () -> pp_print_string fmt (if indirect then "->" else "."))
135
      ?pp_epilogue
136
      (fun fmt (i, _) -> pp_print_string fmt i)
137
      fmt
138

    
139
let pp_reg ?(indirect = true) self fmt paths =
140
  fprintf fmt "%s->%a%s"
141
    self
142
    (pp_instance
143
       ~indirect
144
       ~pp_epilogue:(fun fmt () -> pp_print_string fmt (if indirect then "->" else ".")))
145
    paths
146
    "_reg"
147

    
148
let pp_separated pp_self pp_mem pp_ptr fmt (self, mem, paths, ptrs) =
149
  fprintf
150
    fmt
151
    "\\separated(@[<v>%a, %a%a%a@])"
152
    pp_self
153
    self
154
    pp_mem
155
    mem
156
    (pp_comma_list ~pp_prologue:pp_print_comma
157
       (fun fmt path -> pp_indirect pp_print_string pp_instance fmt (self, path)))
158
    paths
159
    (pp_comma_list ~pp_prologue:pp_print_comma pp_ptr)
160
    ptrs
161

    
162
let pp_separated' self mem fmt (paths, ptrs) =
163
  pp_separated
164
    pp_print_string
165
    pp_print_string
166
    pp_var_decl
167
    fmt
168
    (self, mem, paths, ptrs)
169

    
170
let pp_separated'' =
171
  pp_comma_list
172
    ~pp_prologue:(fun fmt () -> pp_print_string fmt "\\separated(")
173
    ~pp_epilogue:pp_print_cpar
174
    pp_var_decl
175

    
176
let pp_forall pp_l pp_r fmt (l, r) =
177
  fprintf fmt "@[<v 2>\\forall @[<hov>%a@];@,%a@]" pp_l l pp_r r
178

    
179
let pp_exists pp_l pp_r fmt (l, r) =
180
  fprintf fmt "@[<v 2>\\exists %a;@,%a@]" pp_l l pp_r r
181

    
182
let pp_equal pp_l pp_r fmt (l, r) = fprintf fmt "%a == %a" pp_l l pp_r r
183

    
184
let pp_gequal pp_l pp_r fmt (l, r) = fprintf fmt "%a >= %a" pp_l l pp_r r
185

    
186
let pp_implies pp_l pp_r fmt (l, r) =
187
  fprintf fmt "@[<v>%a ==>@ %a@]" pp_l l pp_r r
188

    
189
let pp_and pp_l pp_r fmt (l, r) = fprintf fmt "@[<v>%a @ && %a@]" pp_l l pp_r r
190

    
191
let pp_and_l pp_v fmt =
192
  pp_print_list
193
    ~pp_open_box:pp_open_vbox0
194
    ~pp_sep:(fun fmt () -> fprintf fmt "@,&& ")
195
    ~pp_nil:pp_true
196
    pp_v
197
    fmt
198

    
199
let pp_or pp_l pp_r fmt (l, r) = fprintf fmt "@[<v>%a @ || %a@]" pp_l l pp_r r
200

    
201
let pp_or_l pp_v fmt =
202
  pp_print_list
203
    ~pp_open_box:pp_open_vbox0
204
    ~pp_sep:(fun fmt () -> fprintf fmt "@,|| ")
205
    pp_v
206
    fmt
207

    
208
let pp_not pp fmt = fprintf fmt "!%a" pp
209

    
210
let pp_valid pp = pp_and_l (fun fmt x -> fprintf fmt "\\valid(%a)" pp x)
211

    
212
let pp_valid_read pp fmt = fprintf fmt "\\valid_read(%a)" pp
213

    
214
let pp_old pp fmt = fprintf fmt "\\old(%a)" pp
215

    
216
let pp_ite pp_c pp_t pp_f fmt (c, t, f) =
217
  fprintf fmt "(%a @[<hov>? %a@ : %a)@]" pp_c c pp_t t pp_f f
218

    
219
let pp_paren pp fmt v = fprintf fmt "(%a)" pp v
220

    
221
let pp_initialization pp_mem fmt (name, mem) =
222
  fprintf fmt "%s_initialization(%a)" name pp_mem mem
223

    
224
let pp_init pp_mem fmt (name, mem) = fprintf fmt "%s_init(%a)" name pp_mem mem
225

    
226
let pp_initialization' = pp_initialization pp_print_string
227

    
228
let pp_local m =
229
  pp_c_decl_local_var ~pp_c_basic_type_desc:pp_acsl_basic_type_desc m
230

    
231
let pp_locals m =
232
  pp_comma_list ~pp_open_box:(fun fmt () -> pp_open_hovbox fmt 0) (pp_local m)
233

    
234
let pp_ptr_decl fmt v = pp_ptr fmt v.var_id
235

    
236
let pp_basic_assign_spec ?(pp_op=pp_equal) pp_l pp_r fmt typ var_name value =
237
  if Types.is_real_type typ && !Options.mpfr then assert false
238
    (* Mpfr.pp_inject_assign pp_var fmt (var_name, value) *)
239
  else pp_op pp_l pp_r fmt (var_name, value)
240

    
241
let pp_assign_spec ?pp_op m self_l pp_var_l indirect_l self_r pp_var_r indirect_r fmt
242
    (var_type, var_name, value) =
243
  let depth = expansion_depth value in
244
  let loop_vars = mk_loop_variables m var_type depth in
245
  let reordered_loop_vars = reorder_loop_variables loop_vars in
246
  let aux typ fmt vars =
247
    match vars with
248
    | [] ->
249
      pp_basic_assign_spec ?pp_op
250
        (pp_value_suffix
251
           ~indirect:indirect_l
252
           m
253
           self_l
254
           var_type
255
           loop_vars
256
           pp_var_l)
257
        (pp_value_suffix
258
           ~indirect:indirect_r
259
           m
260
           self_r
261
           var_type
262
           loop_vars
263
           pp_var_r)
264
        fmt
265
        typ
266
        var_name
267
        value
268
    | (_d, LVar _i) :: _q ->
269
      assert false
270
    (* let typ' = Types.array_element_type typ in
271
     * fprintf fmt "@[<v 2>{@,int %s;@,for(%s=0;%s<%a;%s++)@,%a @]@,}"
272
     *   i i i pp_c_dimension d i
273
     *   (aux typ') q *)
274
    | (_d, LInt _r) :: _q ->
275
      assert false
276
    (* let typ' = Types.array_element_type typ in
277
     * let szl = Utils.enumerate (Dimension.size_const_dimension d) in
278
     * fprintf fmt "@[<v 2>{@,%a@]@,}"
279
     *   (pp_print_list (fun fmt i -> r := i; aux typ' fmt q)) szl *)
280
    | _ ->
281
      assert false
282
  in
283
  reset_loop_counter ();
284
  aux var_type fmt reordered_loop_vars
285

    
286
let pp_memory_pack_aux ?i pp_mem pp_self fmt (name, mem, self) =
287
  fprintf
288
    fmt
289
    "%s_pack%a(@[<hov>%a,@ %a@])"
290
    name
291
    (pp_print_option pp_print_int)
292
    i
293
    pp_mem
294
    mem
295
    pp_self
296
    self
297

    
298
let pp_memory_pack pp_mem pp_self fmt (mp, mem, self) =
299
  pp_memory_pack_aux
300
    ?i:mp.mpindex
301
    pp_mem
302
    pp_self
303
    fmt
304
    (mp.mpname.node_id, mem, self)
305

    
306
let pp_transition_aux ?i stateless pp_mem_in pp_mem_out pp_var fmt
307
    (name, vars, mem_in, mem_out) =
308
  fprintf
309
    fmt
310
    "%s_transition%a(@[<hov>%t%a%t@])"
311
    name
312
    (pp_print_option pp_print_int)
313
    i
314
    (fun fmt -> if not stateless then pp_mem_in fmt mem_in)
315
    (pp_comma_list
316
       ~pp_prologue:(fun fmt () -> if not stateless then pp_print_comma fmt ())
317
       pp_var)
318
    vars
319
    (fun fmt -> if not stateless then fprintf fmt ",@ %a" pp_mem_out mem_out)
320

    
321
let pp_transition stateless pp_mem_in pp_mem_out pp_var fmt (t, mem_in, mem_out)
322
    =
323
  pp_transition_aux
324
    ?i:t.tindex
325
    stateless
326
    pp_mem_in
327
    pp_mem_out
328
    pp_var
329
    fmt
330
    (t.tname.node_id, t.tvars, mem_in, mem_out)
331

    
332
let pp_transition_aux' ?i m =
333
  let stateless = fst (get_stateless_status m) in
334
  pp_transition_aux ?i stateless pp_print_string pp_print_string (fun fmt v ->
335
      (if is_output m v then pp_ptr_decl else pp_var_decl) fmt v)
336

    
337
let pp_reset_cleared pp_mem_in pp_mem_out fmt (name, mem_in, mem_out) =
338
  fprintf
339
    fmt
340
    "%s_reset_cleared(@[<hov>%a,@ %a@])"
341
    name
342
    pp_mem_in
343
    mem_in
344
    pp_mem_out
345
    mem_out
346

    
347
let pp_reset_cleared' = pp_reset_cleared pp_print_string pp_print_string
348

    
349
let pp_functional_update mems insts fmt mem =
350
  let rec aux fmt = function
351
    | [] ->
352
      pp_print_string fmt mem
353
    | (x, is_mem) :: fields ->
354
      fprintf
355
        fmt
356
        "{ @[<hov>%a@ \\with .%s%s = %s@] }"
357
        aux
358
        fields
359
        (if is_mem then "_reg." else "")
360
        x
361
        x
362
  in
363
  aux
364
    fmt
365
    (List.map (fun (x, _) -> x, false) (Utils.IMap.bindings insts)
366
    @ List.map (fun x -> x, true) (Utils.ISet.elements mems))
367

    
368
module PrintSpec = struct
369
  type mode =
370
    | MemoryPackMode
371
    | TransitionMode
372
    | TransitionFootprintMode
373
    | ResetIn
374
    | ResetOut
375
    | InstrMode of ident
376

    
377
  let pp_reg mem fmt = function
378
    | ResetFlag ->
379
      fprintf fmt "%s.%s" mem reset_flag_name
380
    | StateVar x ->
381
      fprintf fmt "%s.%a" mem pp_var_decl x
382

    
383
  let not_var v = match v.value_desc with
384
    | Var _ -> false
385
    | _ -> true
386

    
387
  let pp_expr ?(test_output = false) m mem fmt = function
388
    | Val v ->
389
      let pp = pp_c_val ~indirect:false m mem (pp_c_var_read ~test_output m) in
390
      (if not_var v
391
       then if Types.is_bool_type v.value_type
392
         then pp_bool_cast pp
393
         else if Types.is_real_type v.value_type
394
         then pp_double_cast pp
395
         else pp
396
       else pp) fmt v
397
    | Tag (t, _) ->
398
      pp_print_string fmt t
399
    | Var v ->
400
      pp_var_decl fmt v
401
    | Memory r ->
402
      pp_reg mem fmt r
403

    
404
  let pp_predicate mode m mem_in mem_in' mem_out mem_out' fmt p =
405
    let test_output, mem_update =
406
      match mode with
407
      | InstrMode _ ->
408
        true, false
409
      | TransitionFootprintMode ->
410
        false, true
411
      | _ ->
412
        false, false
413
    in
414
    let pp_expr test_output fmt e = pp_expr ~test_output m mem_out fmt e in
415
    match p with
416
    | Transition (stateless, f, inst, i, vars, r, mems, insts) ->
417
      let pp_mem_in, pp_mem_out =
418
        match inst with
419
        | None ->
420
          ( pp_print_string,
421
            if mem_update then pp_functional_update mems insts
422
            else pp_print_string )
423
        | Some inst ->
424
          ( (fun fmt mem_in ->
425
              if r then pp_print_string fmt mem_in
426
              else pp_access' fmt (mem_in, inst)),
427
            fun fmt mem_out -> pp_access' fmt (mem_out, inst) )
428
      in
429
      pp_transition_aux
430
        ?i
431
        stateless
432
        pp_mem_in
433
        pp_mem_out
434
        (pp_expr test_output)
435
        fmt
436
        (f, vars, mem_in', mem_out')
437
    | Reset (_f, inst, r) ->
438
      pp_ite
439
        (pp_c_val m mem_in (pp_c_var_read m))
440
        (pp_equal (pp_reset_flag' ~indirect:false) pp_print_int)
441
        (pp_equal pp_print_string pp_access')
442
        fmt
443
        (r, (mem_out, 1), (mem_out, (mem_in, inst)))
444
    | MemoryPack (f, inst, i) ->
445
      let pp_mem, pp_self =
446
        match inst with
447
        | None ->
448
          pp_print_string, pp_print_string
449
        | Some inst ->
450
          ( (fun fmt mem -> pp_access' fmt (mem, inst)),
451
            fun fmt self -> pp_indirect' fmt (self, inst) )
452
      in
453
      pp_memory_pack_aux ?i pp_mem pp_self fmt (f, mem_out, mem_in)
454
    | ResetCleared f ->
455
      pp_reset_cleared' fmt (f, mem_in, mem_out)
456
    (* fprintf fmt "ResetCleared_%a" pp_print_string f *)
457
    | Initialization ->
458
      ()
459

    
460
  let reset_flag = dummy_var_decl "_reset" Type_predef.type_bool
461

    
462
  let val_of_expr = function
463
    | Val v ->
464
      v
465
    | Tag (t, _) ->
466
      id_to_tag t
467
    | Var v ->
468
      vdecl_to_val v
469
    | Memory (StateVar v) ->
470
      vdecl_to_val v
471
    | Memory ResetFlag ->
472
      vdecl_to_val reset_flag
473

    
474
  let find_arrow loc m =
475
    match List.find_opt (fun (_, (td, _)) -> Arrow.td_is_arrow td) m.minstances with
476
    | Some (f, _) -> Some f
477
    | None ->
478
      Error.pp_warning loc
479
        (fun fmt -> pp_print_string fmt "Generating stateful spec for uninitialized state variables.");
480
      None
481

    
482
  let rec has_memory_val m v =
483
    let has_mem = has_memory_val m in
484
    match v.value_desc with
485
    | Var v ->
486
      is_memory m v
487
    | Array vl | Fun (_, vl) ->
488
      List.exists has_mem vl
489
    | Access (t, i) | Power (t, i) ->
490
      has_mem t || has_mem i
491
    | _ ->
492
      false
493

    
494
  let has_memory m = function Val v -> has_memory_val m v | _ -> false
495

    
496
  let pp_spec mode m fmt f =
497
    let rec pp_spec mode fmt f =
498
      let mem_in, mem_in', indirect_r, mem_out, mem_out', indirect_l =
499
        let self = mk_self m in
500
        let mem = mk_mem m in
501
        let mem_in = mk_mem_in m in
502
        let mem_out = mk_mem_out m in
503
        let mem_reset = mk_mem_reset m in
504
        match mode with
505
        | MemoryPackMode ->
506
          self, self, true, mem, mem, false
507
        | TransitionMode ->
508
          mem_in, mem_in, false, mem_out, mem_out, false
509
        | TransitionFootprintMode ->
510
          mem_in, mem_in, false, mem_out, mem_out, false
511
        | ResetIn ->
512
          mem_reset, mem_reset, false, mem_out, mem_out, false
513
        | ResetOut ->
514
          mem_in, mem_in, false, mem_reset, mem_reset, false
515
        | InstrMode self ->
516
          let mem = "(*" ^ mem ^ ")" in
517
          fprintf str_formatter "%a" (pp_at pp_print_string) (mem, reset_label);
518
          self, flush_str_formatter (), false, mem, mem, false
519
      in
520
      let pp_expr fmt e = pp_expr m mem_out fmt e in
521
      let pp_spec' = pp_spec mode in
522
      match f with
523
      | True ->
524
        pp_true fmt ()
525
      | False ->
526
        pp_false fmt ()
527
      | Equal (a, b) ->
528
        let pp_eq fmt () =
529
          pp_assign_spec
530
            m
531
            mem_out
532
            (pp_c_var_read ~test_output:false m)
533
            indirect_l
534
            mem_in
535
            (pp_c_var_read ~test_output:false m)
536
            indirect_r
537
            fmt
538
            (Spec_common.type_of_value a, val_of_expr a, val_of_expr b)
539
        in
540
        if has_memory m b then
541
          let inst = find_arrow Location.dummy m in
542
          pp_print_option
543
            ~none:pp_eq
544
            (fun fmt inst ->
545
               pp_paren
546
                 (pp_implies (pp_not (pp_initialization pp_access')) pp_eq)
547
                 fmt
548
                 ((Arrow.arrow_id, (mem_in, inst)), ()))
549
            fmt inst
550
        else pp_eq fmt ()
551
      | GEqual (a, b) ->
552
        pp_assign_spec ~pp_op:pp_gequal
553
          m
554
          mem_out
555
          (pp_c_var_read ~test_output:false m)
556
          indirect_l
557
          mem_in
558
          (pp_c_var_read ~test_output:false m)
559
          indirect_r
560
          fmt
561
          (Spec_common.type_of_value a, val_of_expr a, val_of_expr b)
562
      | And fs ->
563
        pp_and_l pp_spec' fmt fs
564
      | Or fs ->
565
        pp_or_l pp_spec' fmt fs
566
      | Imply (a, b) ->
567
        pp_paren (pp_implies pp_spec' pp_spec') fmt (a, b)
568
      | Exists (xs, a) ->
569
        pp_exists (pp_locals m) pp_spec' fmt (xs, a)
570
      | Forall (xs, a) ->
571
        pp_forall (pp_locals m) pp_spec' fmt (xs, a)
572
      | Ternary (e, a, b) ->
573
        pp_ite pp_expr pp_spec' pp_spec' fmt (e, a, b)
574
      | Predicate p ->
575
        pp_predicate mode m mem_in mem_in' mem_out mem_out' fmt p
576
      | StateVarPack ResetFlag ->
577
        let r = vdecl_to_val reset_flag in
578
        pp_assign_spec
579
          m
580
          mem_out
581
          (pp_c_var_read ~test_output:false m)
582
          indirect_l
583
          mem_in
584
          (pp_c_var_read ~test_output:false m)
585
          indirect_r
586
          fmt
587
          (Type_predef.type_bool, r, r)
588
      | StateVarPack (StateVar v) ->
589
        let v' = vdecl_to_val v in
590
        let pp_eq fmt () =
591
          pp_assign_spec
592
            m
593
            mem_out
594
            (pp_c_var_read ~test_output:false m)
595
            indirect_l
596
            mem_in
597
            (pp_c_var_read ~test_output:false m)
598
            indirect_r
599
            fmt
600
            (v.var_type, v', v')
601
        in
602
        let inst = find_arrow Location.dummy m in
603
        pp_print_option
604
          ~none:pp_eq
605
          (fun fmt inst ->
606
             pp_paren
607
               (pp_implies
608
                  (pp_not (pp_initialization pp_access'))
609
                  pp_eq)
610
               fmt
611
               ((Arrow.arrow_id, (mem_out, inst)), ()))
612
          fmt inst
613
      | ExistsMem (f, rc, tr) ->
614
        pp_exists
615
          (pp_machine_decl' ~ghost:true)
616
          (pp_and (pp_spec ResetOut) (pp_spec ResetIn))
617
          fmt
618
          ((f, mk_mem_reset m), (rc, tr))
619
      | Value v ->
620
        pp_c_val m mem_in (pp_c_var_read ~test_output:true m) fmt v
621
    in
622

    
623
    pp_spec mode fmt (Spec_common.red f)
624
end
625

    
626
let pp_predicate pp_l pp_r fmt (l, r) =
627
  fprintf fmt "@[<v 2>predicate %a =@,%a;@]" pp_l l pp_r r
628

    
629
let pp_lemma pp_l pp_r fmt (l, r) =
630
  fprintf fmt "@[<v 2>lemma %a:@,%a;@]" pp_l l pp_r r
631

    
632
let pp_axiomatic pp_l pp_r fmt (l, r) =
633
  fprintf fmt "@[<v 2>axiomatic %a {@,%a@]@;}" pp_l l pp_r r
634

    
635
let pp_axiom pp_l pp_r fmt (l, r) =
636
  fprintf fmt "@[<v 2>axiom %a:@,%a;@]" pp_l l pp_r r
637

    
638
let pp_mem_valid_def fmt m =
639
  if not (fst (get_stateless_status m) || m.mis_contract) then
640
    let name = m.mname.node_id in
641
    let self = mk_self m in
642
    pp_acsl
643
      (pp_predicate
644
         (pp_mem_valid (pp_machine_decl pp_ptr))
645
         (pp_and
646
            (pp_and_l (fun fmt (inst, (td, _)) ->
647
                 if Arrow.td_is_arrow td then
648
                   pp_valid pp_indirect' fmt [ self, inst ]
649
                 else pp_mem_valid pp_indirect' fmt (node_name td, (self, inst))))
650
            (pp_valid pp_print_string)))
651
      fmt
652
      ((name, (name, self)), (m.minstances, [ self ]))
653

    
654
let pp_memory_pack_def m fmt mp =
655
  if not (fst (get_stateless_status m) || m.mis_contract) then
656
    let name = mp.mpname.node_id in
657
    let self = mk_self m in
658
    let mem = mk_mem m in
659
    pp_acsl_cut
660
      (pp_predicate
661
         (pp_memory_pack
662
            (pp_machine_decl' ~ghost:true)
663
            (pp_machine_decl pp_ptr))
664
         (PrintSpec.pp_spec MemoryPackMode m))
665
      fmt
666
      ((mp, (name, mem), (name, self)), mp.mpformula)
667

    
668
let pp_machine_ghost_struct fmt m =
669
  pp_acsl (pp_ghost (pp_machine_struct ~ghost:true)) fmt m
670

    
671
let pp_memory_pack_defs fmt m =
672
  if not (fst (get_stateless_status m)) then
673
    fprintf
674
      fmt
675
      "%a@,%a"
676
      pp_machine_ghost_struct
677
      m
678
      (pp_print_list
679
         ~pp_sep:pp_print_nothing
680
         ~pp_epilogue:pp_print_cut
681
         ~pp_open_box:pp_open_vbox0
682
         (pp_memory_pack_def m))
683
      (snd m.mspec.mmemory_packs)
684

    
685
let pp_transition_def m fmt t =
686
  let name = t.tname.node_id in
687
  let mem_in = mk_mem_in m in
688
  let mem_out = mk_mem_out m in
689
  let stateless = fst (get_stateless_status m) in
690
  pp_acsl
691
    (pp_predicate
692
       (pp_transition
693
          stateless
694
          (pp_machine_decl' ~ghost:true)
695
          (pp_machine_decl' ~ghost:true)
696
          (pp_local m))
697
       (PrintSpec.pp_spec TransitionMode m))
698
    fmt
699
    ((t, (name, mem_in), (name, mem_out)), t.tformula)
700

    
701
let pp_transition_defs fmt m =
702
  pp_print_list
703
    ~pp_epilogue:pp_print_cut
704
    ~pp_open_box:pp_open_vbox0
705
    (pp_transition_def m)
706
    fmt
707
    m.mspec.mtransitions
708

    
709
let pp_transition_footprint fmt t =
710
  fprintf
711
    fmt
712
    "%s_transition%a_footprint"
713
    t.tname.node_id
714
    (pp_print_option pp_print_int)
715
    t.tindex
716

    
717
let pp_transition_footprint_lemma m fmt t =
718
  let name = t.tname.node_id in
719
  let mem_in = mk_mem_in m in
720
  let mem_out = mk_mem_out m in
721
  let stateless = fst (get_stateless_status m) in
722
  let mems =
723
    ISet.(
724
      diff (of_list (List.map (fun v -> v.var_id) m.mmemory)) t.tmem_footprint)
725
  in
726
  let insts =
727
    IMap.(
728
      diff
729
        (of_list (List.map (fun (x, (td, _)) -> x, node_name td) m.minstances))
730
        t.tinst_footprint)
731
  in
732
  let memories =
733
    List.map
734
      (fun v -> { v with var_type = { v.var_type with tid = -1 } })
735
      (List.filter (fun v -> ISet.mem v.var_id mems) m.mmemory)
736
  in
737
  let mems_empty = ISet.is_empty mems in
738
  let insts_empty = IMap.is_empty insts in
739
  let instances = List.map (fun (i, f) -> f, i) (IMap.bindings insts) in
740
  let tr ?mems ?insts () =
741
    Spec_common.mk_transition
742
      ?mems
743
      ?insts
744
      ?i:t.tindex
745
      stateless
746
      name
747
      (vdecls_to_vals t.tvars)
748
  in
749
  if not ((mems_empty && insts_empty) || m.mis_contract) then
750
    pp_acsl_cut
751
      (pp_lemma
752
         pp_transition_footprint
753
         (pp_forall
754
            (pp_machine_decl ~ghost:true (pp_comma_list pp_print_string))
755
            ((if insts_empty then fun pp fmt (_, x) -> pp fmt x
756
             else pp_forall (pp_comma_list (pp_machine_decl' ~ghost:true)))
757
               ((if mems_empty then fun pp fmt (_, x) -> pp fmt x
758
                else pp_forall (pp_locals m))
759
                  (PrintSpec.pp_spec TransitionFootprintMode m)))))
760
      fmt
761
      ( t,
762
        ( (m.mname.node_id, [ mem_in; mem_out ]),
763
          ( instances,
764
            (memories, Forall (t.tvars, Imply (tr (), tr ~mems ~insts ()))) ) )
765
      )
766

    
767
let pp_transition_footprint_lemmas fmt m =
768
  pp_print_list
769
    ~pp_epilogue:pp_print_cut
770
    ~pp_open_box:pp_open_vbox0
771
    ~pp_sep:pp_print_nothing
772
    (pp_transition_footprint_lemma m)
773
    fmt
774
    (List.filter
775
       (fun t -> match t.tindex with Some i when i > 0 -> true | _ -> false)
776
       m.mspec.mtransitions)
777

    
778
let pp_initialization_def fmt m =
779
  if not (fst (get_stateless_status m)) then
780
    let name = m.mname.node_id in
781
    let mem_in = mk_mem_in m in
782
    pp_acsl
783
      (pp_predicate
784
         (pp_initialization (pp_machine_decl' ~ghost:true))
785
         (pp_and_l (fun fmt (i, (td, _)) ->
786
              if Arrow.td_is_arrow td then
787
                pp_initialization pp_access' fmt (node_name td, (mem_in, i))
788
              else
789
                pp_equal
790
                  (pp_reset_flag ~indirect:false pp_access')
791
                  pp_print_int
792
                  fmt
793
                  ((mem_in, i), 1))))
794
      fmt
795
      ((name, (name, mem_in)), m.minstances)
796

    
797
let pp_reset_cleared_def fmt m =
798
  if not (fst (get_stateless_status m)) then
799
    let name = m.mname.node_id in
800
    let mem_in = mk_mem_in m in
801
    let mem_out = mk_mem_out m in
802
    pp_acsl
803
      (pp_predicate
804
         (pp_reset_cleared
805
            (pp_machine_decl' ~ghost:true)
806
            (pp_machine_decl' ~ghost:true))
807
         (pp_ite
808
            (pp_reset_flag' ~indirect:false)
809
            (pp_and
810
               (pp_equal (pp_reset_flag' ~indirect:false) pp_print_int)
811
               pp_initialization')
812
            (pp_equal pp_print_string pp_print_string)))
813
      fmt
814
      ( (name, (name, mem_in), (name, mem_out)),
815
        (mem_in, ((mem_out, 0), (name, mem_out)), (mem_out, mem_in)) )
816

    
817
let pp_register_chain ?(indirect = true) ptr =
818
  pp_print_list
819
    ~pp_prologue:(fun fmt () -> fprintf fmt "%s->" ptr)
820
    ~pp_epilogue:(fun fmt () ->
821
      fprintf fmt "%s_reg._first" (if indirect then "->" else "."))
822
    ~pp_sep:(fun fmt () -> pp_print_string fmt (if indirect then "->" else "."))
823
    (fun fmt (i, _) -> pp_print_string fmt i)
824

    
825
let pp_reset_flag_chain ?(indirect = true) ptr fmt mems =
826
  pp_print_list
827
    ~pp_prologue:(fun fmt () -> fprintf fmt "%s->" ptr)
828
    ~pp_epilogue:(fun fmt () -> pp_reset_flag' ~indirect fmt "")
829
    ~pp_sep:(fun fmt () -> pp_print_string fmt (if indirect then "->" else "."))
830
    (fun fmt (i, _) -> pp_print_string fmt i)
831
    fmt
832
    mems
833

    
834
let pp_arrow_reset_ghost mem fmt inst =
835
  fprintf fmt "%s_reset_ghost(%a)" Arrow.arrow_id pp_indirect' (mem, inst)
836

    
837
module GhostProto : MODIFIERS_GHOST_PROTO = struct
838
  let pp_ghost_parameters ?(cut = true) fmt vs =
839
    fprintf
840
      fmt
841
      "%a%a"
842
      (if cut then pp_print_cut else pp_print_nothing)
843
      ()
844
      (pp_acsl_line'
845
         (pp_ghost (pp_print_parenthesized (fun fmt (x, pp) -> pp fmt x))))
846
      vs
847
end
848

    
849
module HdrMod = struct
850
  module GhostProto = GhostProto
851

    
852
  let pp_machine_decl_prefix _ _ = ()
853

    
854
  let pp_import_arrow fmt () =
855
    fprintf
856
      fmt
857
      "#include \"%s/arrow_spec.h%s\""
858
      (Arrow.arrow_top_decl ()).top_decl_owner
859
      (if !Options.cpp then "pp" else "")
860

    
861
  let pp_predicates fmt machines =
862
    let pp_preds comment pp =
863
      pp_print_list
864
        ~pp_open_box:pp_open_vbox0
865
        ~pp_prologue:(pp_print_endcut comment)
866
        pp
867
        ~pp_epilogue:pp_print_cutcut
868
    in
869
    fprintf
870
      fmt
871
      "%a%a"
872
      (pp_preds "/* ACSL `valid` predicates */" pp_mem_valid_def)
873
      machines
874
      (pp_preds "/* ACSL `memory pack` simulations */" pp_memory_pack_defs)
875
      machines
876

    
877
  let pp_machine_alloc_decl fmt m =
878
    pp_machine_decl_prefix fmt m;
879
    if not (fst (get_stateless_status m)) then
880
      if !Options.static_mem then
881
        (* Static allocation *)
882
        let macro = m, mk_attribute m, mk_instance m in
883
        fprintf
884
          fmt
885
          "%a@,%a@,%a"
886
          (pp_static_declare_macro ~ghost:true)
887
          macro
888
          (pp_static_link_macro ~ghost:true)
889
          macro
890
          (pp_static_alloc_macro ~ghost:true)
891
          macro
892
      else
893
        (* Dynamic allocation *)
894
        (* TODO: handle dynamic alloc *)
895
        assert false
896
  (* fprintf fmt "extern %a;@,extern %a" pp_alloc_prototype
897
   *   (m.mname.node_id, m.mstatic)
898
   *   pp_dealloc_prototype m.mname.node_id *)
899
end
900

    
901
module SrcMod = struct
902
  module GhostProto = GhostProto
903

    
904
  let pp_predicates fmt machines =
905
    let pp_preds comment pp =
906
      pp_print_list
907
        ~pp_open_box:pp_open_vbox0
908
        ~pp_prologue:(pp_print_endcut comment)
909
        pp
910
        ~pp_epilogue:pp_print_cutcut
911
    in
912
    fprintf
913
      fmt
914
      "%a%a%a%a%a%a"
915
      (pp_preds "/* ACSL `valid` predicates */" pp_mem_valid_def)
916
      machines
917
      (pp_preds "/* ACSL `memory pack` simulations */" pp_memory_pack_defs)
918
      machines
919
      (pp_preds "/* ACSL initialization annotations */" pp_initialization_def)
920
      machines
921
      (pp_preds "/* ACSL reset cleared annotations */" pp_reset_cleared_def)
922
      machines
923
      (pp_preds "/* ACSL transition annotations */" pp_transition_defs)
924
      machines
925
      (pp_preds
926
         "/* ACSL transition memory footprints lemmas */"
927
         pp_transition_footprint_lemmas)
928
      machines
929

    
930
  let pp_clear_reset_spec fmt self mem m =
931
    let name = m.mname.node_id in
932
    let arws, narws =
933
      List.partition (fun (_, (td, _)) -> Arrow.td_is_arrow td) m.minstances
934
    in
935
    let mk_insts = List.map (fun x -> [ x ]) in
936
    pp_acsl_cut
937
      (fun fmt () ->
938
        fprintf
939
          fmt
940
          "%a@,\
941
           %a@,\
942
           %a@,\
943
           %a@,\
944
           %a@,\
945
           %a@,\
946
           %a@,\
947
           %a@,\
948
           %a@,\
949
           %a@,\
950
           @[<v 2>behavior reset:@;\
951
           %a@,\
952
           %a@]@,\
953
           @[<v 2>behavior no_reset:@;\
954
           %a@,\
955
           %a@]@,\
956
           complete behaviors;@,\
957
           disjoint behaviors;"
958
          (pp_requires pp_mem_valid')
959
          (name, self)
960
          (pp_requires (pp_separated' self mem))
961
          (mk_insts m.minstances, [])
962
          (pp_requires (pp_memory_pack_aux pp_ptr pp_print_string))
963
          (name, mem, self)
964
          (pp_ensures
965
             (pp_memory_pack_aux
966
                ~i:(fst m.mspec.mmemory_packs)
967
                pp_ptr
968
                pp_print_string))
969
          (name, mem, self)
970
          (pp_assigns pp_reset_flag')
971
          [ self ]
972
          (pp_assigns (pp_register_chain self))
973
          (mk_insts arws)
974
          (pp_assigns (pp_reset_flag_chain self))
975
          (mk_insts narws)
976
          (pp_assigns pp_reset_flag')
977
          [ mem ]
978
          (pp_assigns (pp_register_chain ~indirect:false mem))
979
          (mk_insts arws)
980
          (pp_assigns (pp_reset_flag_chain ~indirect:false mem))
981
          (mk_insts narws)
982
          (pp_assumes (pp_equal pp_reset_flag' pp_print_int))
983
          (mem, 1)
984
          (pp_ensures (pp_initialization pp_ptr))
985
          (name, mem)
986
          (pp_assumes (pp_equal pp_reset_flag' pp_print_int))
987
          (mem, 0)
988
          (pp_ensures (pp_equal pp_ptr (pp_old pp_ptr)))
989
          (mem, mem))
990
      fmt
991
      ()
992

    
993
  let pp_set_reset_spec fmt self mem m =
994
    let name = m.mname.node_id in
995
    pp_acsl_cut
996
      (fun fmt () ->
997
        fprintf
998
          fmt
999
          "%a@,%a@,%a"
1000
          (pp_ensures (pp_memory_pack_aux pp_ptr pp_print_string))
1001
          (name, mem, self)
1002
          (pp_ensures (pp_equal pp_reset_flag' pp_print_int))
1003
          (mem, 1)
1004
          (pp_assigns pp_reset_flag')
1005
          [ self; mem ])
1006
      fmt
1007
      ()
1008

    
1009
  let spec_from_contract c = Spec_common.red (Imply (c.mc_pre, c.mc_post))
1010

    
1011
  let pp_contract m fmt c =
1012
    PrintSpec.pp_spec PrintSpec.TransitionMode m fmt (spec_from_contract c)
1013

    
1014
  let contract_of machines m =
1015
    match m.mspec.mnode_spec with
1016
    | Some spec -> (
1017
      match spec with
1018
      | Contract c ->
1019
        Some c, None
1020
      | NodeSpec f -> (
1021
        let m_f = find_machine f machines in
1022
        match m_f.mspec.mnode_spec with
1023
        | Some (Contract c) ->
1024
          Some c, Some m_f
1025
        | _ ->
1026
          None, None))
1027
    | None ->
1028
      None, None
1029

    
1030
  let pp_init_def fmt m =
1031
    let name = m.mname.node_id in
1032
    let mem = mk_mem m in
1033
    pp_predicate
1034
      (pp_init (pp_machine_decl' ~ghost:true))
1035
      (pp_and pp_initialization' (pp_reset_flag' ~indirect:false))
1036
      fmt
1037
      ((name, (name, mem)), ((name, mem), mem))
1038

    
1039
  let rename n x = sprintf "%s_%d" x n
1040

    
1041
  let rename_var_decl n vd = { vd with var_id = rename n vd.var_id }
1042

    
1043
  let rec rename_value n v =
1044
    {
1045
      v with
1046
      value_desc =
1047
        (match v.value_desc with
1048
        | Machine_code_types.Var v ->
1049
          Machine_code_types.Var (rename_var_decl n v)
1050
        | Fun (f, vs) ->
1051
          Fun (f, List.map (rename_value n) vs)
1052
        | Array vs ->
1053
          Array (List.map (rename_value n) vs)
1054
        | Access (v1, v2) ->
1055
          Access (rename_value n v1, rename_value n v2)
1056
        | Power (v1, v2) ->
1057
          Power (rename_value n v1, rename_value n v2)
1058
        | v ->
1059
          v);
1060
    }
1061

    
1062
  let rename_expression n = function
1063
    | Val v ->
1064
      Val (rename_value n v)
1065
    | Var v ->
1066
      Var (rename_var_decl n v)
1067
    | e ->
1068
      e
1069

    
1070
  let rename_predicate n = function
1071
    | Transition (s, f, inst, i, es, r, mf, mif) ->
1072
      Transition (s, f, inst, i, List.map (rename_expression n) es, r, mf, mif)
1073
    | p ->
1074
      p
1075

    
1076
  let rec rename_formula n = function
1077
    | Equal (e1, e2) ->
1078
      Equal (rename_expression n e1, rename_expression n e2)
1079
    | And fs ->
1080
      And (List.map (rename_formula n) fs)
1081
    | Or fs ->
1082
      Or (List.map (rename_formula n) fs)
1083
    | Imply (f1, f2) ->
1084
      Imply (rename_formula n f1, rename_formula n f2)
1085
    | Exists (xs, f) ->
1086
      Exists (List.map (rename_var_decl n) xs, rename_formula n f)
1087
    | Forall (xs, f) ->
1088
      Forall (List.map (rename_var_decl n) xs, rename_formula n f)
1089
    | Ternary (e, t, f) ->
1090
      Ternary (rename_expression n e, rename_formula n t, rename_formula n f)
1091
    | Predicate p ->
1092
      Predicate (rename_predicate n p)
1093
    | ExistsMem (x, f1, f2) ->
1094
      ExistsMem (rename n x, rename_formula n f1, rename_formula n f2)
1095
    | Value v ->
1096
      Value (rename_value n v)
1097
    | f ->
1098
      f
1099

    
1100
  let rename_contract n c =
1101
    {
1102
      c with
1103
      mc_pre = rename_formula n c.mc_pre;
1104
      mc_post = rename_formula n c.mc_post;
1105
    }
1106

    
1107
  let but_last l = List.(rev (tl (rev l)))
1108

    
1109
  let pp_k_induction_case case m pp_mem_in pp_mem_out pp_vars fmt
1110
      (n, mem_in, mem_out) =
1111
    let name = m.mname.node_id in
1112
    let inputs = m.mstep.step_inputs in
1113
    let outputs = m.mstep.step_outputs in
1114
    fprintf
1115
      fmt
1116
      "%s_%s_%d(@[<hov>%a,@;%a,@;%a@])"
1117
      name
1118
      case
1119
      n
1120
      pp_mem_in
1121
      mem_in
1122
      pp_vars
1123
      (inputs @ outputs)
1124
      pp_mem_out
1125
      mem_out
1126

    
1127
  let pp_k_induction_base_case m = pp_k_induction_case "base" m
1128

    
1129
  let pp_k_induction_inductive_case m = pp_k_induction_case "inductive" m
1130

    
1131
  let pp_base_cases m fmt (c, m_c, k) =
1132
    let name = m.mname.node_id in
1133
    let name_c = m_c.mname.node_id in
1134
    let mem = mk_mem m in
1135
    let mem_c = mk_mem_c m in
1136
    let inputs = m.mstep.step_inputs in
1137
    let outputs = m.mstep.step_outputs in
1138
    let stateless = fst (get_stateless_status m) in
1139
    let stateless_c = fst (get_stateless_status m_c) in
1140
    let l = List.init (k - 1) (fun n -> n + 1) in
1141
    pp_print_list
1142
      ~pp_open_box:pp_open_vbox0
1143
      ~pp_sep:pp_print_cutcut
1144
      (fun fmt n ->
1145
        let l = List.init (n + 1) (fun n -> n) in
1146
        let pp fmt =
1147
          let pp =
1148
            pp_implies
1149
              (pp_and_l (fun fmt -> function
1150
                 | 0 ->
1151
                   let pp = pp_init pp_print_string in
1152
                   (if stateless_c then fun fmt (x, _) -> pp fmt x
1153
                   else pp_and pp pp)
1154
                     fmt
1155
                     ((name, rename 0 mem), (name_c, rename 0 mem_c))
1156
                 | n' ->
1157
                   let pp_var_c fmt (out, vd) =
1158
                     if out && n' < n then pp_true_c_bool fmt ()
1159
                     else pp_var_decl fmt vd
1160
                   in
1161
                   let c_inputs =
1162
                     List.map
1163
                       (fun v -> false, rename_var_decl n' v)
1164
                       m_c.mstep.step_inputs
1165
                   in
1166
                   let c_outputs =
1167
                     List.map
1168
                       (fun v -> true, rename_var_decl n' v)
1169
                       m_c.mstep.step_outputs
1170
                   in
1171
                   let pp stateless pp_var =
1172
                     pp_transition_aux
1173
                       stateless
1174
                       pp_print_string
1175
                       pp_print_string
1176
                       pp_var
1177
                   in
1178
                   pp_and
1179
                     (pp stateless pp_var_decl)
1180
                     (pp stateless_c pp_var_c)
1181
                     fmt
1182
                     ( ( name,
1183
                         List.map (rename_var_decl n') (inputs @ outputs),
1184
                         rename (n' - 1) mem,
1185
                         rename n' mem ),
1186
                       ( name_c,
1187
                         c_inputs @ c_outputs,
1188
                         rename (n' - 1) mem_c,
1189
                         rename n' mem_c ) )))
1190
              (pp_contract m)
1191
          in
1192
          if stateless_c then pp fmt
1193
          else fun x ->
1194
            pp_forall
1195
              (pp_machine_decl
1196
                 ~ghost:true
1197
                 (pp_comma_list (fun fmt n ->
1198
                      pp_print_string fmt (rename n mem_c))))
1199
              pp
1200
              fmt
1201
              ((name_c, l), x)
1202
        in
1203
        pp_predicate
1204
          (pp_k_induction_base_case
1205
             m
1206
             (pp_machine_decl' ~ghost:true)
1207
             (pp_machine_decl' ~ghost:true)
1208
             (fun fmt xs -> pp_locals m fmt (List.map (rename_var_decl n) xs)))
1209
          (pp_forall
1210
             (pp_locals m)
1211
             (if n > 1 then
1212
              pp_forall
1213
                (fun fmt l ->
1214
                  fprintf
1215
                    fmt
1216
                    "%a@,%a"
1217
                    (pp_machine_decl
1218
                       ~ghost:true
1219
                       (pp_comma_list ~pp_eol:pp_print_comma (fun fmt n ->
1220
                            pp_print_string fmt (rename n mem))))
1221
                    (name, but_last l)
1222
                    (pp_locals m)
1223
                    (List.flatten
1224
                       (List.map
1225
                          (fun n ->
1226
                            List.map (rename_var_decl n) (inputs @ outputs))
1227
                          (List.tl l))))
1228
                pp
1229
             else fun fmt (_, x) -> pp fmt x))
1230
          fmt
1231
          ( (n, (name, rename (n - 1) mem), (name, rename n mem)),
1232
            ( List.map (rename_var_decl n) m_c.mstep.step_outputs,
1233
              (but_last l, (l, rename_contract n c)) ) ))
1234
      fmt
1235
      l
1236

    
1237
  let pp_inductive_case m fmt (c, m_c, k) =
1238
    let name = m.mname.node_id in
1239
    let mem = mk_mem m in
1240
    let mem_c = mk_mem_c m_c in
1241
    let inputs = m.mstep.step_inputs in
1242
    let outputs = m.mstep.step_outputs in
1243
    let stateless = fst (get_stateless_status m) in
1244
    let stateless_c = fst (get_stateless_status m_c) in
1245
    let l = List.init k (fun n -> n + 1) in
1246
    let l' = 0 :: l in
1247
    let pp fmt =
1248
      let pp =
1249
        pp_implies
1250
          (pp_and_l (fun fmt n ->
1251
               let pp_var_c fmt (out, vd) =
1252
                 if out && n < k then pp_true_c_bool fmt ()
1253
                 else pp_var_decl fmt vd
1254
               in
1255
               let c_inputs =
1256
                 List.map
1257
                   (fun v -> false, rename_var_decl n v)
1258
                   m_c.mstep.step_inputs
1259
               in
1260
               let c_outputs =
1261
                 List.map
1262
                   (fun v -> true, rename_var_decl n v)
1263
                   m_c.mstep.step_outputs
1264
               in
1265
               pp_and
1266
                 (pp_transition_aux
1267
                    stateless
1268
                    pp_print_string
1269
                    pp_print_string
1270
                    pp_var_decl)
1271
                 (pp_transition_aux
1272
                    stateless_c
1273
                    pp_print_string
1274
                    pp_print_string
1275
                    pp_var_c)
1276
                 fmt
1277
                 ( ( name,
1278
                     List.map (rename_var_decl n) (inputs @ outputs),
1279
                     rename (n - 1) mem,
1280
                     rename n mem ),
1281
                   ( m_c.mname.node_id,
1282
                     c_inputs @ c_outputs,
1283
                     rename (n - 1) mem_c,
1284
                     rename n mem_c ) )))
1285
          (pp_contract m)
1286
      in
1287
      if stateless_c then pp fmt
1288
      else fun x ->
1289
        pp_forall
1290
          (pp_machine_decl
1291
             ~ghost:true
1292
             (pp_comma_list (fun fmt n -> pp_print_string fmt (rename n mem_c))))
1293
          pp
1294
          fmt
1295
          ((m_c.mname.node_id, l'), x)
1296
    in
1297
    pp_predicate
1298
      (pp_k_induction_inductive_case
1299
         m
1300
         (pp_machine_decl' ~ghost:true)
1301
         (pp_machine_decl' ~ghost:true)
1302
         (fun fmt xs -> pp_locals m fmt (List.map (rename_var_decl k) xs)))
1303
      (pp_forall
1304
         (pp_locals m)
1305
         (if k > 1 then
1306
          pp_forall
1307
            (fun fmt l ->
1308
              fprintf
1309
                fmt
1310
                "%a@,%a"
1311
                (pp_machine_decl
1312
                   ~ghost:true
1313
                   (pp_comma_list ~pp_eol:pp_print_comma (fun fmt n ->
1314
                        pp_print_string fmt (rename (n - 1) mem))))
1315
                (name, but_last l)
1316
                (pp_locals m)
1317
                (List.flatten
1318
                   (List.map
1319
                      (fun n ->
1320
                        List.map (rename_var_decl (n - 1)) (inputs @ outputs))
1321
                      (List.tl l))))
1322
            pp
1323
         else fun fmt (_, x) -> pp fmt x))
1324
      fmt
1325
      ( (k, (name, rename (k - 1) mem), (name, rename k mem)),
1326
        ( List.map (rename_var_decl k) m_c.mstep.step_outputs,
1327
          (l, (l, rename_contract k c)) ) )
1328

    
1329
  let pp_k_induction_lemmas m fmt k =
1330
    let name = m.mname.node_id in
1331
    let mem_in = mk_mem_in m in
1332
    let mem_out = mk_mem_out m in
1333
    let inputs = m.mstep.step_inputs in
1334
    let outputs = m.mstep.step_outputs in
1335
    let l = List.init k (fun n -> n + 1) in
1336
    pp_print_list
1337
      ~pp_open_box:pp_open_vbox0
1338
      ~pp_sep:pp_print_cutcut
1339
      (fun fmt n ->
1340
        pp_lemma
1341
          (fun fmt n -> fprintf fmt "%s_k_induction_%d" name n)
1342
          (pp_forall
1343
             (fun fmt () ->
1344
               fprintf
1345
                 fmt
1346
                 "%a,@;%a"
1347
                 (pp_machine_decl ~ghost:true (pp_comma_list pp_print_string))
1348
                 (name, [ mem_in; mem_out ])
1349
                 (pp_locals m)
1350
                 (inputs @ outputs))
1351
             ((if n = k then pp_k_induction_inductive_case
1352
              else pp_k_induction_base_case)
1353
                m
1354
                pp_print_string
1355
                pp_print_string
1356
                (pp_comma_list pp_var_decl)))
1357
          fmt
1358
          (n, ((), (n, mem_in, mem_out))))
1359
      fmt
1360
      l
1361

    
1362
  let pp_k_induction_axiom m fmt (c, m_c, k) =
1363
    let name = m.mname.node_id in
1364
    let mem_in = mk_mem_in m in
1365
    let mem_out = mk_mem_out m in
1366
    let mem_in_c = mk_mem_in_c m_c in
1367
    let mem_out_c = mk_mem_out_c m_c in
1368
    let inputs = m.mstep.step_inputs in
1369
    let outputs = m.mstep.step_outputs in
1370
    let stateless = fst (get_stateless_status m) in
1371
    let stateless_c = fst (get_stateless_status m_c) in
1372
    let l = List.init k (fun n -> n + 1) in
1373
    let pp =
1374
      pp_implies
1375
        (pp_and_l (fun fmt n ->
1376
             (if n = k then pp_k_induction_inductive_case
1377
             else pp_k_induction_base_case)
1378
               m
1379
               pp_print_string
1380
               pp_print_string
1381
               (pp_comma_list pp_var_decl)
1382
               fmt
1383
               (n, mem_in, mem_out)))
1384
        (pp_forall
1385
           (pp_locals m)
1386
           (pp_implies
1387
              (pp_and
1388
                 (pp_transition_aux
1389
                    stateless
1390
                    pp_print_string
1391
                    pp_print_string
1392
                    pp_var_decl)
1393
                 (pp_transition_aux
1394
                    stateless_c
1395
                    pp_print_string
1396
                    pp_print_string
1397
                    pp_var_decl))
1398
              (pp_contract m)))
1399
    in
1400
    pp_axiomatic
1401
      (fun fmt () -> fprintf fmt "%s_k_Induction" name)
1402
      (pp_axiom
1403
         (fun fmt () -> fprintf fmt "%s_k_induction" name)
1404
         (pp_forall
1405
            (fun fmt () ->
1406
              fprintf
1407
                fmt
1408
                "%a,@;%a"
1409
                (pp_machine_decl ~ghost:true (pp_comma_list pp_print_string))
1410
                (name, [ mem_in; mem_out ])
1411
                (pp_locals m)
1412
                (inputs @ outputs))
1413
            (if stateless_c then pp
1414
            else fun fmt x ->
1415
              pp_forall
1416
                (pp_machine_decl ~ghost:true (pp_comma_list pp_print_string))
1417
                pp
1418
                fmt
1419
                ((m_c.mname.node_id, [ mem_in_c; mem_out_c ]), x))))
1420
      fmt
1421
      ( (),
1422
        ( (),
1423
          ( (),
1424
            ( l,
1425
              ( m_c.mstep.step_outputs,
1426
                ( ( (name, inputs @ outputs, mem_in, mem_out),
1427
                    ( m_c.mname.node_id,
1428
                      m_c.mstep.step_inputs @ m_c.mstep.step_outputs,
1429
                      mem_in_c,
1430
                      mem_out_c ) ),
1431
                  c ) ) ) ) ) )
1432

    
1433
  let pp_k_induction m fmt ((_, m_c, k) as c_m_k) =
1434
    let stateless_c = fst (get_stateless_status m_c) in
1435
    pp_acsl_cut
1436
      (fun fmt () ->
1437
        fprintf
1438
          fmt
1439
          "%a@,@,%a@,@,%a@,@,%a@,@,%a@,@,%a"
1440
          pp_init_def
1441
          m
1442
          (if stateless_c then pp_print_nothing else pp_init_def)
1443
          m_c
1444
          (pp_base_cases m)
1445
          c_m_k
1446
          (pp_inductive_case m)
1447
          c_m_k
1448
          (pp_k_induction_lemmas m)
1449
          k
1450
          (pp_k_induction_axiom m)
1451
          c_m_k)
1452
      fmt
1453
      ()
1454

    
1455
  let pp_proof_annotation m m_c fmt c =
1456
    let pp m_c fmt = function
1457
      | Kinduction k ->
1458
        pp_k_induction m fmt (c, m_c, k)
1459
    in
1460
    match m_c with
1461
    | Some m_c ->
1462
      pp_print_option (pp m_c) fmt c.mc_proof
1463
    | None ->
1464
      ()
1465

    
1466
  let pp_step_spec fmt machines self mem m =
1467
    let name = m.mname.node_id in
1468
    let insts = instances machines m in
1469
    let insts_no_arrow =
1470
      List.(filter
1471
              (fun path ->
1472
                 let _, (td, _) = hd (rev path) in
1473
                 not (Arrow.td_is_arrow td))
1474
              insts)
1475
    in
1476
    let stateful_insts =
1477
      List.(filter
1478
              (fun path ->
1479
                 let _, (_, mems) = hd (rev path) in
1480
                 mems <> [])
1481
              insts)
1482
    in
1483
    let inputs = m.mstep.step_inputs in
1484
    let outputs = m.mstep.step_outputs in
1485
    let stateless = fst (get_stateless_status m) in
1486
    let pp_if_outputs pp = if outputs = [] then pp_print_nothing else pp in
1487
    let c, m_c = contract_of machines m in
1488
    let pp_spec =
1489
      pp_print_option
1490
        (if m.mis_contract then pp_print_nothing
1491
        else fun fmt c ->
1492
          pp_print_option
1493
            (fun fmt m_c ->
1494
              let mem_in = mk_mem_in_c m_c in
1495
              let mem_out = mk_mem_out_c m_c in
1496
              let stateless_c = fst (get_stateless_status m_c) in
1497
              pp_ensures
1498
                (pp_implies
1499
                   (pp_transition_aux
1500
                      stateless_c
1501
                      pp_print_string
1502
                      pp_print_string
1503
                      (fun fmt v ->
1504
                        (if is_output m v then pp_ptr_decl else pp_var_decl)
1505
                          fmt
1506
                          v))
1507
                   (pp_contract m))
1508
                fmt
1509
                ( ( m_c.mname.node_id,
1510
                    m_c.mstep.step_inputs @ m_c.mstep.step_outputs,
1511
                    mem_in,
1512
                    mem_out ),
1513
                  c ))
1514
            fmt
1515
            m_c)
1516
    in
1517
    let pp_spec_vars =
1518
      match m_c with
1519
      | Some m_c ->
1520
        let mem_in = mk_mem_in_c m_c in
1521
        let mem_out = mk_mem_out_c m_c in
1522
        let stateless_c = fst (get_stateless_status m_c) in
1523
        pp_acsl_cut
1524
          (pp_ghost (fun fmt () ->
1525
               fprintf
1526
                 fmt
1527
                 "@;<0 2>@[<v>%a%a@]"
1528
                 (pp_print_list
1529
                    ~pp_open_box:pp_open_vbox0
1530
                    ~pp_sep:pp_print_semicolon
1531
                    ~pp_eol:pp_print_semicolon
1532
                    (pp_c_decl_local_var m))
1533
                 m_c.mstep.step_outputs
1534
                 (if stateless_c then pp_print_nothing
1535
                 else
1536
                   pp_machine_decl
1537
                     ~ghost:true
1538
                     (pp_comma_list ~pp_eol:pp_print_semicolon pp_print_string))
1539
                 (m_c.mname.node_id, [ mem_in; mem_out ])))
1540
      | _ ->
1541
        pp_print_nothing
1542
    in
1543
    pp_print_option (pp_proof_annotation m m_c) fmt c;
1544
    pp_spec_vars fmt ();
1545
    pp_acsl_cut
1546
      (fun fmt () ->
1547
        if stateless then
1548
          fprintf
1549
            fmt
1550
            "%a@,%a@,%a@,%a@,%a"
1551
            (pp_if_outputs (pp_requires (pp_valid pp_var_decl)))
1552
            outputs
1553
            (pp_if_outputs (pp_requires pp_separated''))
1554
            outputs
1555
            (pp_assigns pp_ptr_decl)
1556
            outputs
1557
            (pp_ensures (pp_transition_aux' m))
1558
            (name, inputs @ outputs, "", "")
1559
            pp_spec
1560
            c
1561
        else
1562
          fprintf
1563
            fmt
1564
            "%a@,\
1565
             %a@,\
1566
             %a@,\
1567
             %a@,\
1568
             %a@,\
1569
             %a@,\
1570
             %a@,\
1571
             %a@,\
1572
             %a@,\
1573
             %a@,\
1574
             %a@,\
1575
             %a@,\
1576
             %a@,\
1577
             %a@,\
1578
             %a@,\
1579
             %a"
1580
            (pp_if_outputs (pp_requires (pp_valid pp_var_decl)))
1581
            outputs
1582
            (pp_requires pp_mem_valid')
1583
            (name, self)
1584
            (pp_requires (pp_separated' self mem))
1585
            (insts, outputs)
1586
            (pp_requires (pp_memory_pack_aux pp_ptr pp_print_string))
1587
            (name, mem, self)
1588
            (pp_ensures (pp_memory_pack_aux pp_ptr pp_print_string))
1589
            (name, mem, self)
1590
            (pp_ensures
1591
               (pp_transition_aux stateless (pp_old pp_ptr) pp_ptr (fun fmt v ->
1592
                    (if is_output m v then pp_ptr_decl else pp_var_decl) fmt v)))
1593
            (name, inputs @ outputs, mem, mem)
1594
            pp_spec
1595
            c
1596
            (pp_assigns pp_ptr_decl)
1597
            outputs
1598
            (if m.mmemory = [] then pp_print_nothing else pp_assigns (pp_reg self))
1599
            [[]]
1600
            (pp_assigns pp_reset_flag')
1601
            [ self ]
1602
            (pp_assigns (pp_reg self))
1603
            stateful_insts
1604
            (pp_assigns (pp_reset_flag_chain self))
1605
            insts_no_arrow
1606
            (if m.mmemory = [] then pp_print_nothing else pp_assigns (pp_reg mem))
1607
            [[]]
1608
            (pp_assigns pp_reset_flag')
1609
            [ mem ]
1610
            (pp_assigns (pp_reg ~indirect:false mem))
1611
            stateful_insts
1612
            (pp_assigns (pp_reset_flag_chain ~indirect:false mem))
1613
            insts_no_arrow)
1614
      fmt
1615
      ()
1616

    
1617
  let pp_ghost_instr_code m self fmt instr =
1618
    match instr.instr_desc with
1619
    | MStateAssign (x, v) ->
1620
      fprintf
1621
        fmt
1622
        "@,%a"
1623
        (pp_acsl_line (pp_ghost (pp_assign m self (pp_c_var_read m))))
1624
        (x, v)
1625
    | MResetAssign b ->
1626
      fprintf fmt "@,%a" (pp_acsl_line (pp_ghost (pp_reset_assign self))) b
1627
    | MSetReset inst ->
1628
      let td, _ = List.assoc inst m.minstances in
1629
      if Arrow.td_is_arrow td then
1630
        fprintf
1631
          fmt
1632
          "@,%a;"
1633
          (pp_acsl_line (pp_ghost (pp_arrow_reset_ghost self)))
1634
          inst
1635
    | _ ->
1636
      ()
1637

    
1638
  let pp_step_instr_spec m self mem fmt instr =
1639
    let ghost = m.mis_contract in
1640
    fprintf
1641
      fmt
1642
      "%a%a"
1643
      (pp_ghost_instr_code m mem)
1644
      instr
1645
      (pp_print_list
1646
         ~pp_open_box:pp_open_vbox0
1647
         ~pp_prologue:pp_print_cut
1648
         (pp_acsl_line'
1649
            ~ghost
1650
            (pp_assert (PrintSpec.pp_spec (InstrMode self) m))))
1651
      instr.instr_spec
1652

    
1653
  let pp_ghost_parameter mem fmt inst =
1654
    GhostProto.pp_ghost_parameters
1655
      ~cut:false
1656
      fmt
1657
      (match inst with
1658
      | Some inst ->
1659
        [ (inst, fun fmt inst -> pp_ref pp_indirect' fmt (mem, inst)) ]
1660
      | None ->
1661
        [ mem, pp_print_string ])
1662

    
1663
  let pp_contract fmt machines _self mem m =
1664
    let pp_vars ?pp_eol = pp_comma_list ?pp_eol (pp_c_var_read m) in
1665
    match contract_of machines m with
1666
    | Some c, Some _ ->
1667
      pp_print_option
1668
        (pp_acsl_cut (fun fmt -> function
1669
           | Kinduction k ->
1670
             let l = List.init k (fun n -> n + 1) in
1671
             let pp_mem_in = pp_at_pre pp_ptr in
1672
             let pp_mem_out = pp_ptr in
1673
             pp_assert
1674
               (pp_and_l (fun fmt n ->
1675
                    (if n = k then pp_k_induction_inductive_case
1676
                    else pp_k_induction_base_case)
1677
                      m
1678
                      pp_mem_in
1679
                      pp_mem_out
1680
                      pp_vars
1681
                      fmt
1682
                      (n, mem, mem)))
1683
               fmt
1684
               l))
1685
        fmt
1686
        c.mc_proof
1687
    | _, _ ->
1688
      ()
1689
end
1690

    
1691
module MainMod = struct
1692
  let main_mem_ghost = "main_mem_ghost"
1693

    
1694
  let pp_declare_ghost_state fmt name =
1695
    pp_acsl_line'_cut
1696
      (pp_ghost (fun fmt () ->
1697
           fprintf
1698
             fmt
1699
             "%a(,%s);"
1700
             (pp_machine_static_alloc_name ~ghost:true)
1701
             name
1702
             main_mem_ghost))
1703
      fmt
1704
      ()
1705

    
1706
  let pp_ghost_state_parameter fmt () =
1707
    GhostProto.pp_ghost_parameters
1708
      ~cut:false
1709
      fmt
1710
      [ main_mem_ghost, pp_ref pp_print_string ]
1711

    
1712
  let pp_main_loop_invariants main_mem machines fmt m =
1713
    let name = m.mname.node_id in
1714
    let insts = instances machines m in
1715
    pp_acsl_cut
1716
      (fun fmt () ->
1717
        fprintf
1718
          fmt
1719
          "%a@,%a@,%a@,%a"
1720
          (pp_loop_invariant pp_mem_valid')
1721
          (name, main_mem)
1722
          (pp_loop_invariant
1723
             (pp_memory_pack_aux pp_print_string pp_print_string))
1724
          (name, main_mem_ghost, main_mem)
1725
          (pp_loop_invariant
1726
             (pp_separated
1727
                (pp_paren pp_print_string)
1728
                pp_ref'
1729
                (pp_ref pp_var_decl)))
1730
          (main_mem, main_mem_ghost, insts, m.mstep.step_outputs)
1731
          (pp_loop_invariant
1732
             (pp_or (pp_valid_read pp_stdout) (pp_equal pp_stdout pp_null)))
1733
          ((), ((), ())))
1734
      fmt
1735
      ()
1736

    
1737
  let pp_main_spec fmt =
1738
    pp_acsl_cut
1739
      (fun fmt () ->
1740
        fprintf
1741
          fmt
1742
          "%a@,%a@,%a@,%a"
1743
          (pp_requires
1744
             (pp_or (pp_valid_read pp_stdout) (pp_equal pp_stdout pp_null)))
1745
          ((), ((), ()))
1746
          (pp_terminates pp_false)
1747
          ()
1748
          (pp_ensures pp_false)
1749
          ()
1750
          (pp_assigns pp_nothing)
1751
          [ () ])
1752
      fmt
1753
      ()
1754
end
1755

    
1756
(**************************************************************************)
1757
(*                              MAKEFILE                                  *)
1758
(**************************************************************************)
1759

    
1760
module MakefileMod = struct
1761
  let pp_print_dependencies = C_backend_makefile.fprintf_dependencies "_spec"
1762

    
1763
  let pp_arrow_o fmt () = pp_print_string fmt "arrow_spec.o"
1764

    
1765
  let other_targets fmt basename _nodename dependencies =
1766
    fprintf fmt "FRAMACEACSL=`frama-c -print-share-path`/e-acsl@.";
1767
    (* EACSL version of library file . c *)
1768
    fprintf fmt "%s_eacsl.c: %s.c %s.h@." basename basename basename;
1769
    fprintf
1770
      fmt
1771
      "\tframa-c -e-acsl-full-mmodel -machdep x86_64 -e-acsl %s.c -then-on \
1772
       e-acsl -print -ocode %s_eacsl.c@."
1773
      basename
1774
      basename;
1775
    fprintf fmt "@.";
1776
    fprintf fmt "@.";
1777

    
1778
    (* EACSL version of library file . c + main .c *)
1779
    fprintf
1780
      fmt
1781
      "%s_main_eacsl.c: %s.c %s.h %s_main.c@."
1782
      basename
1783
      basename
1784
      basename
1785
      basename;
1786
    fprintf
1787
      fmt
1788
      "\tframa-c -e-acsl-full-mmodel -machdep x86_64 -e-acsl %s.c %s_main.c \
1789
       -then-on e-acsl -print -ocode %s_main_eacsl.i@."
1790
      basename
1791
      basename
1792
      basename;
1793
    (* Ugly hack to deal with eacsl bugs *)
1794
    fprintf
1795
      fmt
1796
      "\tgrep -v _fc_stdout %s_main_eacsl.i > %s_main_eacsl.c"
1797
      basename
1798
      basename;
1799
    fprintf fmt "@.";
1800
    fprintf fmt "@.";
1801

    
1802
    (* EACSL version of binary *)
1803
    fprintf fmt "%s_main_eacsl: %s_main_eacsl.c@." basename basename;
1804
    fprintf
1805
      fmt
1806
      "\t${GCC} -Wno-attributes -I${INC} -I. -c %s_main_eacsl.c@."
1807
      basename;
1808
    (* compiling instrumented lib + main *)
1809
    pp_print_dependencies fmt dependencies;
1810
    fprintf
1811
      fmt
1812
      "\t${GCC} -Wno-attributes -o %s_main_eacsl io_frontend.o %a %s \
1813
       %s_main_eacsl.o %a@."
1814
      basename
1815
      (pp_print_list (fun fmt dep -> fprintf fmt "%s.o" dep.name))
1816
      (C_backend_makefile.compiled_dependencies dependencies)
1817
      ("${FRAMACEACSL}/e_acsl.c "
1818
     ^ "${FRAMACEACSL}/memory_model/e_acsl_bittree.c "
1819
     ^ "${FRAMACEACSL}/memory_model/e_acsl_mmodel.c")
1820
      basename
1821
      (pp_print_list (fun fmt lib -> fprintf fmt "-l%s" lib))
1822
      (C_backend_makefile.lib_dependencies dependencies);
1823
    fprintf fmt "@."
1824
end
1825

    
1826
(* TODO: complete this list *)
1827
let acsl_keywords = ISet.of_list ["set"]
1828

    
1829
let sanitize x = if ISet.mem x acsl_keywords then "__" ^ x else x
1830

    
1831
let sanitize_var_decl vd = { vd with var_id = sanitize vd.var_id }
1832

    
1833
let sanitize_var_decls = List.map sanitize_var_decl
1834

    
1835
let rec sanitize_value v =
1836
  let value_desc = match v.value_desc with
1837
    | Machine_code_types.Var vd -> Machine_code_types.Var (sanitize_var_decl vd)
1838
    | Fun (f, vs) -> Fun (f, sanitize_values vs)
1839
    | Array vs -> Array (sanitize_values vs)
1840
    | Access (v1, v2) -> Access (sanitize_value v1, sanitize_value v2)
1841
    | Power (v1, v2) -> Power (sanitize_value v1, sanitize_value v2)
1842
    | v -> v
1843
  in
1844
  { v with value_desc }
1845

    
1846
and sanitize_values vs = List.map sanitize_value vs
1847

    
1848
let sanitize_expr = function
1849
  | Val v -> Val (sanitize_value v)
1850
  | Var v -> Var (sanitize_var_decl v)
1851
  | e -> e
1852

    
1853
let sanitize_predicate = function
1854
  | Transition (st, f, inst, i, vs, r, mf, mfinsts) ->
1855
    Transition (st, f, inst, i, List.map sanitize_expr vs, r, mf, mfinsts)
1856
  | p -> p
1857

    
1858
let rec sanitize_formula = function
1859
  | Equal (e1, e2) -> Equal (sanitize_expr e1, sanitize_expr e2)
1860
  | GEqual (e1, e2) -> GEqual (sanitize_expr e1, sanitize_expr e2)
1861
  | And fs -> And (sanitize_formulae fs)
1862
  | Or fs -> Or (sanitize_formulae fs)
1863
  | Imply (f1, f2) -> Imply (sanitize_formula f1, sanitize_formula f2)
1864
  | Exists (vs, f) -> Exists (sanitize_var_decls vs, sanitize_formula f)
1865
  | Forall (vs, f) -> Forall (sanitize_var_decls vs, sanitize_formula f)
1866
  | Ternary (e, t, f) -> Ternary (sanitize_expr e, sanitize_formula t, sanitize_formula f)
1867
  | Predicate p -> Predicate (sanitize_predicate p)
1868
  | ExistsMem (m, f1, f2) -> ExistsMem (m, sanitize_formula f1, sanitize_formula f2)
1869
  | Value v -> Value (sanitize_value v)
1870
  | f -> f
1871

    
1872
and sanitize_formulae fs = List.map sanitize_formula fs
1873

    
1874
let rec sanitize_instr i =
1875
  let sanitize_instr_desc = function
1876
    | MLocalAssign (x, v) ->
1877
      MLocalAssign (sanitize_var_decl x, sanitize_value v)
1878
    | MStateAssign (x, v) ->
1879
      MStateAssign (x, sanitize_value v)
1880
    | MStep (xs, f, vs) ->
1881
      MStep (sanitize_var_decls xs, f, sanitize_values vs)
1882
    | MBranch (v, brs) ->
1883
      MBranch (sanitize_value v, List.map (fun (t, instrs) -> t, sanitize_instrs instrs) brs)
1884
    | i -> i
1885
  in
1886
  { i with
1887
    instr_desc = sanitize_instr_desc i.instr_desc;
1888
    instr_spec = sanitize_formulae i.instr_spec
1889
  }
1890

    
1891
and sanitize_instrs instrs = List.map sanitize_instr instrs
1892

    
1893
let sanitize_step s =
1894
  { s with
1895
    step_inputs = sanitize_var_decls s.step_inputs;
1896
    step_outputs = sanitize_var_decls s.step_outputs;
1897
    step_locals = sanitize_var_decls s.step_locals;
1898
    step_instrs = sanitize_instrs s.step_instrs
1899
  }
1900

    
1901
let sanitize_transition t =
1902
  { t with
1903
    tvars = sanitize_var_decls t.tvars;
1904
    tformula = sanitize_formula t.tformula
1905
  }
1906

    
1907
let sanitize_transitions = List.map sanitize_transition
1908

    
1909
let sanitize_memory_pack mp =
1910
  { mp with
1911
    mpformula = sanitize_formula mp.mpformula
1912
  }
1913

    
1914
let sanitize_memory_packs (n, mps) = n, List.map sanitize_memory_pack mps
1915

    
1916
let sanitize_spec s =
1917
  { s with
1918
    mtransitions = sanitize_transitions s.mtransitions;
1919
    mmemory_packs = sanitize_memory_packs s.mmemory_packs
1920
  }
1921
let sanitize_machine m =
1922
  { m with
1923
    mstep = sanitize_step m.mstep;
1924
    mspec = sanitize_spec m.mspec
1925
  }
1926

    
1927
let sanitize_machines = List.map sanitize_machine
1928

    
1929
(* Local Variables: *)
1930
(* compile-command:"make -C ../../.." *)
1931
(* End: *)
(15-15/18)