Project

General

Profile

Download (10.6 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

    
29
  let suffixOld = "_old"
30
  let suffixNew = "_new"
31
  let pp_transition_name fmt = fprintf fmt "transition"
32
  let pp_state_name_transition suffix fmt = fprintf fmt "%t%s" pp_state_name suffix
33

    
34

    
35

    
36

    
37
  (** Printing function for basic assignement [var := value].
38

    
39
      @param fmt the formater to print on
40
      @param var_name the name of the variable
41
      @param value the value to be assigned
42
   **)
43
  let pp_local_eq env fmt var value =
44
    fprintf fmt "%t = %a"
45
      (pp_var_name var)
46
      (pp_value env) value
47

    
48
  (** Printing function for basic assignement [var := value].
49

    
50
      @param fmt the formater to print on
51
      @param var_name the name of the variable
52
      @param value the value to be assigned
53
   **)
54
  let pp_state_eq env fmt var value =
55
    fprintf fmt "%t = %a"
56
      (pp_access (pp_state_name_transition suffixNew) (pp_var_name var))
57
      (pp_value env) value
58

    
59
  (** Printing function for instruction. See
60
      {!type:Machine_code_types.instr_t} for more details on
61
      machine types.
62

    
63
      @param typed_submachines list of all typed machine instances of this machine
64
      @param machine the current machine
65
      @param fmt the formater to print on
66
      @param instr the instruction to print
67
   **)
68
  let rec pp_machine_instr typed_submachines env instr fmt =
69
    let pp_instr = pp_machine_instr typed_submachines env in
70
    let pp_state suffix i fmt = fprintf fmt "%t.%s" (pp_state_name_transition suffix) i in
71
    match get_instr_desc instr with
72
      (* no reset *)
73
      | MNoReset _ -> ()
74
      (* reset  *)
75
      | MReset i when List.mem_assoc i typed_submachines ->
76
          let (substitution, submachine) = get_instance i typed_submachines in
77
          let pp_package = pp_package_name_with_polymorphic substitution submachine in
78
          let args = if is_machine_statefull submachine then [[pp_state suffixOld i;pp_state suffixNew i]] else [] in
79
          pp_call fmt (pp_package_access (pp_package, pp_reset_procedure_name), args)
80
      | MLocalAssign (ident, value) ->
81
          pp_local_eq env fmt ident value
82
      | MStateAssign (ident, value) ->
83
          pp_state_eq env fmt ident value
84
      | MStep ([i0], i, vl) when is_builtin_fun i ->
85
          let value = mk_val (Fun (i, vl)) i0.var_type in
86
          if List.mem_assoc i0.var_id env then
87
            pp_state_eq env fmt i0 value
88
          else
89
            pp_local_eq env fmt i0 value
90
          
91
      | MStep (il, i, vl) when List.mem_assoc i typed_submachines ->
92
          let (substitution, submachine) = get_instance i typed_submachines in
93
          let pp_package = pp_package_name_with_polymorphic substitution submachine in
94
          let input = List.map (fun x fmt -> pp_value env fmt x) vl in
95
          let output = List.map pp_var_name il in
96
          let args =
97
            (if is_machine_statefull submachine then [[pp_state suffixOld i;pp_state suffixNew i]] else [])
98
              @(if input!=[] then [input] else [])
99
              @(if output!=[] then [output] else [])
100
          in
101
          fprintf fmt "(%a)" pp_call (pp_package_access (pp_package, pp_transition_name), args)
102
      | MComment s -> ()
103
      | _ -> assert false
104

    
105

    
106

    
107

    
108

    
109

    
110

    
111

    
112

    
113

    
114

    
115

    
116

    
117

    
118

    
119

    
120

    
121

    
122
  (** Print the expression function representing the transition predicate.
123
     @param fmt the formater to print on
124
     @param machine the machine
125
  **)
126
  let pp_transition_predicate prototype typed_submachines fmt (opt_spec_machine, m) =
127
    let old_state = (AdaIn, pp_state_name_transition suffixOld, pp_state_type, None) in
128
    let new_state = (AdaIn, pp_state_name_transition suffixNew, pp_state_type, None) in
129
    let env = List.map (fun x -> x.var_id, pp_state_name_transition suffixOld) m.mmemory in
130
    let inputs = build_pp_var_decl_step_input AdaIn None m in
131
    let outputs = build_pp_var_decl_step_output AdaIn None m in
132
    let instrs = push_if_in_expr m.mstep.step_instrs in
133
    let content = List.map (pp_machine_instr typed_submachines env) instrs in
134
    let locals = List.map (fun x-> (pp_var_name x, fun fmt -> pp_var_type fmt x)) m.mstep.step_locals in
135
    pp_predicate pp_transition_name ([[old_state; new_state]]@inputs@outputs) fmt (if prototype then None else Some (locals, content))
136
    
137

    
138

    
139

    
140

    
141

    
142

    
143

    
144

    
145

    
146

    
147

    
148

    
149
  (** Print a new statement instantiating a generic package.
150
     @param fmt the formater to print on
151
     @param substitutions the instanciation substitution
152
     @param machine the machine to instanciate
153
  **)
154
  let pp_new_package fmt (substitutions, machine) =
155
    let pp_name = pp_package_name machine in
156
    let pp_new_name = pp_package_name_with_polymorphic substitutions machine in
157
    let instanciations = List.map (fun (id, typ) -> (pp_polymorphic_type id, fun fmt -> pp_type fmt typ)) substitutions in
158
    pp_package_instanciation pp_new_name pp_name fmt instanciations
159

    
160
  (** Remove duplicates from a list according to a given predicate.
161
     @param eq the predicate defining equality
162
     @param l the list to parse
163
  **)
164
  let remove_duplicates eq l =
165
    let aux l x = if List.exists (eq x) l then l else x::l in
166
    List.fold_left aux [] l
167

    
168

    
169
  (** Compare two typed machines.
170
  **)
171
  let eq_typed_machine (subst1, machine1) (subst2, machine2) =
172
    (String.equal machine1.mname.node_id machine2.mname.node_id) &&
173
    (List.for_all2 (fun a b -> pp_eq_type (snd a) (snd b)) subst1 subst2)
174

    
175

    
176
  (** Print the package declaration(ads) of a machine.
177
    It requires the list of all typed instance.
178
    A typed submachine is a (ident, typed_machine) with
179
      - ident: the name 
180
      - typed_machine: a (substitution, machine) with
181
        - machine: the submachine struct
182
        - substitution the instanciation of all its polymorphic types.
183
     @param fmt the formater to print on
184
     @param typed_submachines list of all typed submachines of this machine
185
     @param m the machine
186
  **)
187
  let pp_file fmt (typed_submachines, ((m_spec_opt, guarantees), m)) =
188
    let typed_machines = snd (List.split typed_submachines) in
189
    let typed_machines_set = remove_duplicates eq_typed_machine typed_machines in
190
    
191
    let machines_to_import = List.map pp_package_name (snd (List.split typed_machines_set)) in
192

    
193
    let polymorphic_types = find_all_polymorphic_type m in
194
    
195
    let typed_machines_to_instanciate =
196
      List.filter (fun (l, _) -> l != []) typed_machines_set in
197

    
198
    let typed_instances = List.filter is_submachine_statefull typed_submachines in
199

    
200
    let pp_state_decl_and_reset fmt = fprintf fmt "%t;@,@,%a;@,@,"
201
      (*Declare the state type*)
202
      (pp_type_decl pp_state_type AdaPrivate)
203
      (*Declare the reset procedure*)
204
      (pp_procedure pp_reset_procedure_name (build_pp_arg_reset m) None) AdaNoContent
205
    in
206
    
207
    let vars_spec = match m_spec_opt with
208
      | None -> []
209
      | Some m_spec -> List.map (build_pp_var_decl AdaNoMode None) m_spec.mstep.step_locals
210
    in
211
    let vars = List.map (build_pp_var_decl AdaNoMode None) m.mmemory in
212
    let states = List.map (build_pp_state_decl_from_subinstance AdaNoMode None) typed_instances in
213
    let var_lists =
214
      (if states = [] then [] else [states]) @
215
      (if vars = [] then [] else [vars])@
216
      (if vars_spec = [] then [] else [vars_spec]) in
217
    
218
    let pp_ifstatefull fmt pp =
219
      if is_machine_statefull m then
220
        fprintf fmt "%t" pp
221
      else
222
        fprintf fmt ""
223
    in
224

    
225
    let pp_private_section fmt = fprintf fmt "@,private@,@,%a%t%a;@,@,%a"
226
      (*Instantiate the polymorphic type that need to be instantiated*)
227
      (Utils.fprintf_list ~sep:";@," pp_new_package) typed_machines_to_instanciate
228
      (Utils.pp_final_char_if_non_empty ";@,@," typed_machines_to_instanciate)
229
      (*Define the state type*)
230
      pp_ifstatefull (fun fmt-> pp_record pp_state_type fmt var_lists)
231
        
232
      (*Declare the transition predicate*)
233
      (pp_transition_predicate false typed_submachines) (m_spec_opt, m)
234
    in
235

    
236
    let pp_content fmt =
237
      let pp_contract_opt =
238
        let ghost_memory = match m_spec_opt with
239
          | None -> []
240
          | Some m_spec -> m_spec.mstep.step_locals
241
        in
242
        let pp_var x fmt =
243
          if List.exists (fun var -> var.var_id == x) ghost_memory then
244
            pp_access pp_state_name (fun fmt -> pp_clean_ada_identifier fmt x) fmt
245
          else
246
            pp_clean_ada_identifier fmt x
247
        in
248
        let input = List.map pp_var_name m.mstep.step_inputs in
249
        let output = List.map pp_var_name m.mstep.step_outputs in
250
        let args =
251
          (if is_machine_statefull m then [[pp_old pp_state_name;pp_state_name]] else [])
252
            @(if input!=[] then [input] else [])
253
            @(if output!=[] then [output] else [])
254
        in
255
        let transition fmt = pp_call fmt (pp_transition_name, args) in
256
        match guarantees with
257
          | [] -> Some (false, [], [transition])
258
          | _ ->  Some (false, [], transition::(List.map pp_var guarantees))
259
      in
260
      fprintf fmt "%a%a%a@,@,%a;%t" (* %a;@, *)
261
        pp_ifstatefull pp_state_decl_and_reset
262
        
263
        (*Declare the step procedure*)
264
        (pp_procedure pp_step_procedure_name (build_pp_arg_step m) pp_contract_opt) AdaNoContent
265
        
266
        pp_ifstatefull (fun fmt -> fprintf fmt ";@,")
267
        
268
        (*Declare the transition predicate*)
269
        (pp_transition_predicate true typed_submachines) (m_spec_opt, m)
270
        
271
        (*Print the private section*)
272
        pp_private_section
273
    in
274
    
275
    let pp_poly_types id = pp_type_decl (pp_polymorphic_type id) AdaPrivate in
276
    let pp_generics = List.map pp_poly_types polymorphic_types in
277
    
278
    fprintf fmt "@[<v>%a%t%a;@]@."
279
      
280
      (* Include all the subinstance package*)
281
      (Utils.fprintf_list ~sep:";@," (pp_with AdaPrivate)) machines_to_import
282
      (Utils.pp_final_char_if_non_empty ";@,@," machines_to_import)
283
      
284
      (*Begin the package*)
285
      (pp_package (pp_package_name m) pp_generics false) pp_content
286

    
287
end
(5-5/12)