Project

General

Profile

Download (8.31 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
(** Main module for generating packages bodies
25
 **)
26
module Main =
27
struct
28

    
29
  (** Printing function for basic assignement [var_name := value].
30

    
31
      @param fmt the formater to print on
32
      @param var_name the name of the variable
33
      @param value the value to be assigned
34
   **)
35
  let pp_basic_assign m fmt var_name value =
36
    fprintf fmt "%a := %a"
37
      (pp_access_var m) var_name
38
      (pp_value m) value
39

    
40
  (** Printing function for instruction. See
41
      {!type:Machine_code_types.instr_t} for more details on
42
      machine types.
43

    
44
      @param typed_submachines list of all typed machine instances of this machine
45
      @param machine the current machine
46
      @param fmt the formater to print on
47
      @param instr the instruction to print
48
   **)
49
  let rec pp_machine_instr typed_submachines machine instr fmt =
50
    let pp_instr = pp_machine_instr typed_submachines machine in
51
    (* Print args for a step call *)
52
    let pp_state i fmt = fprintf fmt "%t.%s" pp_state_name i in
53
    (* Print a when branch of a case *)
54
    let pp_when (cond, instrs) fmt =
55
      fprintf fmt "when %s =>@,%a" cond pp_block (List.map pp_instr instrs)
56
    in
57
    (* Print a case *)
58
    let pp_case fmt (g, hl) =
59
      fprintf fmt "case %a is@,%aend case"
60
        (pp_value machine) g
61
        pp_block (List.map pp_when hl)
62
    in
63
    (* Print a if *)
64
    (* If neg is true the we must test for the negation of the condition. It
65
       first check that we don't have a negation and a else case, if so it
66
       inverses the two branch and remove the negation doing a recursive
67
       call. *)
68
    let rec pp_if neg fmt (g, instrs1, instrs2) =
69
      match neg, instrs2 with
70
        | true, Some x -> pp_if false fmt (g, x, Some instrs1)
71
        | _ ->
72
          let pp_cond =
73
            if neg then
74
              fun fmt x -> fprintf fmt "! (%a)" (pp_value machine) x
75
            else
76
              pp_value machine
77
          in
78
          let pp_else = match instrs2 with
79
            | None -> fun fmt -> fprintf fmt ""
80
            | Some i2 -> fun fmt ->
81
                fprintf fmt "else@,%a" pp_block (List.map pp_instr i2)
82
          in
83
          fprintf fmt "if %a then@,%a%tend if"
84
            pp_cond g
85
            pp_block (List.map pp_instr instrs1)
86
            pp_else
87
    in
88
    match get_instr_desc instr with
89
      (* no reset *)
90
      | MNoReset _ -> ()
91
      (* reset  *)
92
      | MReset i when List.mem_assoc i typed_submachines ->
93
          let (substitution, submachine) = get_instance i typed_submachines in
94
          let pp_package = pp_package_name_with_polymorphic substitution submachine in
95
          let args = if is_machine_statefull submachine then [[pp_state i]] else [] in
96
          pp_call fmt (pp_package_access (pp_package, pp_reset_procedure_name), args)
97
      | MLocalAssign (ident, value) ->
98
          pp_basic_assign machine fmt ident value
99
      | MStateAssign (ident, value) ->
100
          pp_basic_assign machine fmt ident value
101
      | MStep ([i0], i, vl) when is_builtin_fun i ->
102
          let value = mk_val (Fun (i, vl)) i0.var_type in
103
          pp_basic_assign machine fmt i0 value
104
      | MStep (il, i, vl) when List.mem_assoc i typed_submachines ->
105
          let (substitution, submachine) = get_instance i typed_submachines in
106
          let pp_package = pp_package_name_with_polymorphic substitution submachine in
107
          let input = List.map (fun x fmt -> pp_value machine fmt x) vl in
108
          let output = List.map (fun x fmt -> pp_var_name fmt x) il in
109
          let args =
110
            (if is_machine_statefull submachine then [[pp_state i]] else [])
111
              @(if input!=[] then [input] else [])
112
              @(if output!=[] then [output] else [])
113
          in
114
          pp_call fmt (pp_package_access (pp_package, pp_step_procedure_name), args)
115
      | MBranch (_, []) -> assert false
116
      | MBranch (g, (c1, i1)::tl) when c1=tag_false || c1=tag_true ->
117
          let neg = c1=tag_false in
118
          let other = match tl with
119
            | []         -> None
120
            | [(c2, i2)] -> Some i2
121
            | _          -> assert false
122
          in
123
          pp_if neg fmt (g, i1, other)
124
      | MBranch (g, hl) -> pp_case fmt (g, hl)
125
      | MComment s  ->
126
          let lines = String.split_on_char '\n' s in
127
          fprintf fmt "%a" (Utils.fprintf_list ~sep:"" pp_oneline_comment) lines
128
      | _ -> assert false
129

    
130
  (** Print the definition of the step procedure from a machine.
131

    
132
     @param typed_submachines list of all typed machine instances of this machine
133
     @param fmt the formater to print on
134
     @param machine the machine
135
  **)
136
  let pp_step_definition typed_submachines fmt (m, m_spec_opt) =
137
    let spec_instrs = match m_spec_opt with
138
      | None -> []
139
      | Some m -> m.mstep.step_instrs
140
    in
141
    let spec_locals = match m_spec_opt with
142
      | None -> []
143
      | Some m -> m.mstep.step_locals
144
    in
145
    let pp_local_list = List.map build_pp_var_decl_local (m.mstep.step_locals@spec_locals) in
146
    let pp_instr_list = List.map (pp_machine_instr typed_submachines m) (m.mstep.step_instrs@spec_instrs) in
147
    let content = AdaProcedureContent ((if pp_local_list = [] then [] else [pp_local_list]), pp_instr_list) in
148
    pp_procedure pp_step_procedure_name (build_pp_arg_step m) None fmt content
149

    
150
  (** Print the definition of the reset procedure from a machine.
151

    
152
     @param typed_submachines list of all typed machine instances of this machine
153
     @param fmt the formater to print on
154
     @param machine the machine
155
  **)
156
  let pp_reset_definition typed_submachines fmt m =
157
    let build_assign = function var ->
158
      mkinstr (MStateAssign (var, mk_default_value var.var_type))
159
    in
160
    let assigns = List.map build_assign m.mmemory in
161
    let pp_instr_list = List.map (pp_machine_instr typed_submachines m) (assigns@m.minit) in
162
    pp_procedure pp_reset_procedure_name (build_pp_arg_reset m) None fmt (AdaProcedureContent ([], pp_instr_list))
163

    
164
  (** Print the package definition(ads) of a machine.
165
    It requires the list of all typed instance.
166
    A typed submachine instance is (ident, type_machine) with ident
167
    the instance name and typed_machine is (substitution, machine) with machine
168
    the machine associated to the instance and substitution the instanciation of
169
    all its polymorphic types.
170
     @param fmt the formater to print on
171
     @param typed_submachines list of all typed machine instances of this machine
172
     @param m the machine
173
  **)
174
  let pp_file fmt (typed_submachines, ((opt_spec_machine, guarantees), machine)) =
175
    let pp_reset fmt =
176
      if is_machine_statefull machine then
177
        fprintf fmt "%a;@,@," (pp_reset_definition typed_submachines) machine
178
      else
179
        fprintf fmt ""
180
    in
181
    let aux pkgs (id, _) =
182
      try
183
        let (pkg, _) = List.assoc id ada_supported_funs in
184
        if List.mem pkg pkgs then
185
          pkgs
186
        else
187
          pkg::pkgs
188
      with Not_found -> pkgs
189
    in
190
    let packages = List.map pp_str (List.fold_left aux [] machine.mcalls) in
191
    let pp_content fmt =
192
      fprintf fmt "%t%a"
193
        (*Define the reset procedure*)
194
        pp_reset
195
        
196
        (*Define the step procedure*)
197
        (pp_step_definition typed_submachines) (machine, opt_spec_machine)
198
    in
199
    fprintf fmt "%a%t%a;@."
200
      
201
      (* Include all the required packages*)
202
      (Utils.fprintf_list ~sep:";@," (pp_with AdaNoVisibility)) packages
203
      (Utils.pp_final_char_if_non_empty ";@,@," packages)
204
      
205
      (*Print package*)
206
      (pp_package (pp_package_name machine) [] true ) pp_content
207

    
208
end
209

    
210
(* Local Variables: *)
211
(* compile-command: "make -C ../../.." *)
212
(* End: *)
(4-4/12)