Project

General

Profile

Download (10.9 KB) Statistics
| Branch: | Tag: | Revision:
1
(********************************************************************)
2
(*                                                                  *)
3
(*  The LustreC compiler toolset   /  The LustreC Development Team  *)
4
(*  Copyright 2012 -    --   ONERA - CNRS - INPT - ISAE-SUPAERO     *)
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

    
12
open Format
13

    
14
open Machine_code_types
15
open Lustre_types
16
open Corelang
17
open Machine_code_common
18

    
19
open Misc_printer
20
open Misc_lustre_function
21
open Ada_printer
22
open Ada_backend_common
23

    
24
(** Functions printing the .ads file **)
25
module Main =
26
struct
27

    
28
  (** Print a new statement instantiating a generic package.
29
     @param fmt the formater to print on
30
     @param substitutions the instanciation substitution
31
     @param machine the machine to instanciate
32
  **)
33
  let pp_new_package fmt (substitutions, machine) =
34
    let pp_name = pp_package_name machine in
35
    let pp_new_name = pp_package_name_with_polymorphic substitutions machine in
36
    let instanciations = List.map (fun (id, typ) -> (pp_polymorphic_type id, fun fmt -> pp_type fmt typ)) substitutions in
37
    pp_package_instanciation pp_new_name pp_name fmt instanciations
38

    
39
  (** Print a precondition in aspect
40
     @param fmt the formater to print on
41
     @param expr the expession to print as pre
42
  **)
43
  let pp_pre fmt expr =
44
    fprintf fmt "Pre => %a"
45
      pp_clean_ada_identifier expr
46

    
47
  (** Print a postcondition in aspect
48
     @param fmt the formater to print on
49
     @param expr the expession to print as pre
50
  **)
51
  let pp_post fmt ident =
52
    fprintf fmt "Post => %a"
53
      pp_clean_ada_identifier ident
54

    
55
  (** Print the declaration of a procedure with a contract
56
     @param pp_prototype the prototype printer
57
     @param fmt the formater to print on
58
     @param contract the contract for the function to declare
59
  **)
60
  let pp_contract guarantees fmt =
61
    fprintf fmt "@,  @[<v>Global => null%t%a@]"
62
      (Utils.pp_final_char_if_non_empty ",@," guarantees)
63
      (Utils.fprintf_list ~sep:",@," pp_post) guarantees
64

    
65
(*
66
  let pp_transition_name fmt = fprintf fmt "transition"
67
  let pp_state_name_transition suffix fmt = fprintf fmt "%t_%s" pp_state_name suffix
68

    
69
  (** Printing function for basic assignement [var_name := value].
70

    
71
      @param fmt the formater to print on
72
      @param var_name the name of the variable
73
      @param value the value to be assigned
74
   **)
75
  let pp_basic_assign m fmt var_name value =
76
    fprintf fmt "%a = %a"
77
      (pp_access_var m) var_name
78
      (pp_value m) value
79

    
80

    
81
  (** Printing function for instruction. See
82
      {!type:Machine_code_types.instr_t} for more details on
83
      machine types.
84

    
85
      @param typed_submachines list of all typed machine instances of this machine
86
      @param machine the current machine
87
      @param fmt the formater to print on
88
      @param instr the instruction to print
89
   **)
90
  let rec pp_machine_instr typed_submachines machine instr fmt =
91
    let pp_instr = pp_machine_instr typed_submachines machine in
92
    (* Print args for a step call *)
93
    let pp_state i fmt = fprintf fmt "%t.%s" pp_state_name i in
94
    let pp_args vl il fmt =
95
      fprintf fmt "@[%a@]%t@[%a@]"
96
        (Utils.fprintf_list ~sep:",@ " (pp_value machine)) vl
97
        (Utils.pp_final_char_if_non_empty ",@," il)
98
        (Utils.fprintf_list ~sep:",@ " pp_var_name) il
99
    in
100
    (* Print a when branch of a case *)
101
    let pp_when (cond, instrs) fmt =
102
      fprintf fmt "when %s =>@,%a" cond pp_block (List.map pp_instr instrs)
103
    in
104
    (* Print a case *)
105
    let pp_case fmt (g, hl) =
106
      fprintf fmt "case %a is@,%aend case"
107
        (pp_value machine) g
108
        pp_block (List.map pp_when hl)
109
    in
110
    (* Print a if *)
111
    (* If neg is true the we must test for the negation of the condition. It
112
       first check that we don't have a negation and a else case, if so it
113
       inverses the two branch and remove the negation doing a recursive
114
       call. *)
115
    let rec pp_if neg fmt (g, instrs1, instrs2) =
116
      match neg, instrs2 with
117
        | true, Some x -> pp_if false fmt (g, x, Some instrs1)
118
        | _ ->
119
          let pp_cond =
120
            if neg then
121
              fun fmt x -> fprintf fmt "! (%a)" (pp_value machine) x
122
            else
123
              pp_value machine
124
          in
125
          let pp_else = match instrs2 with
126
            | None -> fun fmt -> fprintf fmt ""
127
            | Some i2 -> fun fmt ->
128
                fprintf fmt "else@,%a" pp_block (List.map pp_instr i2)
129
          in
130
          fprintf fmt "if %a then@,%a%tend if"
131
            pp_cond g
132
            pp_block (List.map pp_instr instrs1)
133
            pp_else
134
    in
135
    match get_instr_desc instr with
136
      (* no reset *)
137
      | MNoReset _ -> ()
138
      (* reset  *)
139
      | MReset i when List.mem_assoc i typed_submachines ->
140
          let (substitution, submachine) = get_instance i typed_submachines in
141
          let pp_package = pp_package_name_with_polymorphic substitution submachine in
142
          pp_call fmt (pp_package_access (pp_package, pp_name), [pp_state i])
143
      | MLocalAssign (ident, value) ->
144
          pp_basic_assign machine fmt ident value
145
      | MStateAssign (ident, value) ->
146
          pp_basic_assign machine fmt ident value
147
      | MStep ([i0], i, vl) when is_builtin_fun i ->
148
          let value = mk_val (Fun (i, vl)) i0.var_type in
149
          pp_basic_assign machine fmt i0 value
150
      | MStep (il, i, vl) when List.mem_assoc i typed_submachines ->
151
          let (substitution, submachine) = get_instance i typed_submachines in
152
          pp_package_call
153
            pp_step_procedure_name
154
            fmt
155
            (substitution, submachine, pp_state i, Some (pp_args vl il))
156
      | MBranch (_, []) -> assert false
157
      | MBranch (g, (c1, i1)::tl) when c1=tag_false || c1=tag_true ->
158
          let neg = c1=tag_false in
159
          let other = match tl with
160
            | []         -> None
161
            | [(c2, i2)] -> Some i2
162
            | _          -> assert false
163
          in
164
          pp_if neg fmt (g, i1, other)
165
      | MBranch (g, hl) -> pp_case fmt (g, hl)
166
      | MComment s  ->
167
          let lines = String.split_on_char '\n' s in
168
          fprintf fmt "%a" (Utils.fprintf_list ~sep:"" pp_oneline_comment) lines
169
      | _ -> assert false
170

    
171
  (** Print the expression function representing the transition predicate.
172
     @param fmt the formater to print on
173
     @param machine the machine
174
  **)
175
  let pp_transition_predicate typed_submachines fmt (opt_spec_machine, m) =
176
    let spec_instrs = match opt_spec_machine with
177
      | None -> []
178
      | Some m -> m.mstep.step_instrs
179
    in
180
    fprintf fmt "function %t (%a; %a) return Boolean is (@,  @[<v>%a@,@]) with Ghost"
181
      pp_transition_name
182
      pp_var_decl_mode (In, pp_state_name_transition "old", pp_state_type)
183
      pp_var_decl_mode (In, pp_state_name_transition "new", pp_state_type)
184
      (Utils.fprintf_list ~sep:" and@," (pp_machine_instr typed_submachines m)) (m.mstep.step_instrs@spec_instrs)*)
185
    
186
  (** Remove duplicates from a list according to a given predicate.
187
     @param eq the predicate defining equality
188
     @param l the list to parse
189
  **)
190
  let remove_duplicates eq l =
191
    let aux l x = if List.exists (eq x) l then l else x::l in
192
    List.fold_left aux [] l
193

    
194

    
195
  (** Compare two typed machines.
196
  **)
197
  let eq_typed_machine (subst1, machine1) (subst2, machine2) =
198
    (String.equal machine1.mname.node_id machine2.mname.node_id) &&
199
    (List.for_all2 (fun a b -> pp_eq_type (snd a) (snd b)) subst1 subst2)
200

    
201

    
202
  (** Print the package declaration(ads) of a machine.
203
    It requires the list of all typed instance.
204
    A typed submachine is a (ident, typed_machine) with
205
      - ident: the name 
206
      - typed_machine: a (substitution, machine) with
207
        - machine: the submachine struct
208
        - substitution the instanciation of all its polymorphic types.
209
     @param fmt the formater to print on
210
     @param typed_submachines list of all typed submachines of this machine
211
     @param m the machine
212
  **)
213
  let pp_file fmt (typed_submachines, ((opt_spec_machine, guarantees), m)) =
214
    let typed_machines = snd (List.split typed_submachines) in
215
    let typed_machines_set = remove_duplicates eq_typed_machine typed_machines in
216
    
217
    let machines_to_import = List.map pp_package_name (snd (List.split typed_machines_set)) in
218

    
219
    let polymorphic_types = find_all_polymorphic_type m in
220
    
221
    let typed_machines_to_instanciate =
222
      List.filter (fun (l, _) -> l != []) typed_machines_set in
223

    
224
    let typed_instances = List.filter is_submachine_statefull typed_submachines in
225

    
226
    let pp_state_decl_and_reset fmt = fprintf fmt "%t;@,@,%a;@,@,"
227
      (*Declare the state type*)
228
      (pp_type_decl pp_state_type AdaLimitedPrivate)
229
      (*Declare the reset procedure*)
230
      (pp_procedure pp_reset_procedure_name (build_pp_arg_reset m) None) AdaNoContent
231
    in
232

    
233
    let vars = List.map (build_pp_var_decl AdaNoMode) m.mmemory in
234
    let states = List.map build_pp_state_decl_from_subinstance typed_instances in
235
    let var_lists = (if vars = [] then [] else [vars])@(if states = [] then [] else [states]) in
236

    
237
    let pp_private_section fmt = fprintf fmt "@,private@,@,%a%t%a"
238
      (*Instantiate the polymorphic type that need to be instantiated*)
239
      (Utils.fprintf_list ~sep:";@," pp_new_package) typed_machines_to_instanciate
240
      (Utils.pp_final_char_if_non_empty ";@,@," typed_machines_to_instanciate)
241
      (*Define the state type*)
242
      (pp_record pp_state_type) var_lists
243
    in
244
    
245
    let pp_ifstatefull fmt pp =
246
      if is_machine_statefull m then
247
        fprintf fmt "%t" pp
248
      else
249
        fprintf fmt ""
250
    in
251

    
252
    let pp_content fmt =
253
      let pp_contract_opt = match guarantees with
254
                              | [] -> None
255
                              | _ ->  Some (pp_contract guarantees) in
256
      fprintf fmt "%a%a%a%a" (* %a;@, *)
257
        pp_ifstatefull pp_state_decl_and_reset
258
        
259
        (*Declare the transition predicate*)
260
        (* pp_transition_predicate typed_submachines) (opt_spec_machine, m) *)
261
        
262
        (*Declare the step procedure*)
263
        (pp_procedure pp_step_procedure_name (build_pp_arg_step m) pp_contract_opt) AdaNoContent
264
        
265
        pp_ifstatefull (fun fmt -> fprintf fmt ";@,")
266
        
267
        (*Print the private section*)
268
        pp_ifstatefull pp_private_section
269
    in
270
    
271
    let pp_poly_types id = pp_type_decl (pp_polymorphic_type id) AdaPrivate in
272
    let pp_generics = List.map pp_poly_types polymorphic_types in
273
    
274
    fprintf fmt "@[<v>%a%t%a;@]@."
275
      
276
      (* Include all the subinstance package*)
277
      (Utils.fprintf_list ~sep:";@," (pp_with AdaPrivate)) machines_to_import
278
      (Utils.pp_final_char_if_non_empty ";@,@," machines_to_import)
279
      
280
      (*Begin the package*)
281
      (pp_package (pp_package_name m) pp_generics false) pp_content
282

    
283
end
(5-5/12)