Project

General

Profile

Download (14 KB) Statistics
| Branch: | Tag: | Revision:
1
open Format
2

    
3
open Machine_code_types
4
open Lustre_types
5
open Corelang
6
open Machine_code_common
7

    
8
open Ada_printer
9
open Misc_printer
10
open Misc_lustre_function
11

    
12
(** Exception for unsupported features in Ada backend **)
13
exception Ada_not_supported of string
14

    
15
(** Print the name of the state variable.
16
   @param fmt the formater to print on
17
**)
18
let pp_state_name fmt = fprintf fmt "state"
19
(** Print the type of the state variable.
20
   @param fmt the formater to print on
21
**)
22
let pp_state_type fmt = fprintf fmt "TState"
23
(** Print the name of the reset procedure
24
   @param fmt the formater to print on
25
**)
26
let pp_reset_procedure_name fmt = fprintf fmt "reset"
27
(** Print the name of the step procedure
28
   @param fmt the formater to print on
29
**)
30
let pp_step_procedure_name fmt = fprintf fmt "step"
31
(** Print the name of the main procedure.
32
   @param fmt the formater to print on
33
**)
34
let pp_main_procedure_name fmt = fprintf fmt "ada_main"
35
(** Print the name of the arrow package.
36
   @param fmt the formater to print on
37
**)
38
let pp_arrow_package_name fmt = fprintf fmt "Arrow"
39
(** Print the type of a polymorphic type.
40
   @param fmt the formater to print on
41
   @param id the id of the polymorphic type
42
**)
43
let pp_polymorphic_type id fmt = fprintf fmt "T_%i" id
44

    
45

    
46

    
47

    
48

    
49

    
50

    
51

    
52

    
53
(*TODO Check all this function with unit test, improve this system and
54
   add support for : "cbrt", "erf", "log10", "pow", "atan2".
55
*)
56
let ada_supported_funs =
57
  [("sqrt",  ("Ada.Numerics.Elementary_Functions", "Sqrt"));
58
   ("log",   ("Ada.Numerics.Elementary_Functions", "Log"));
59
   ("exp",   ("Ada.Numerics.Elementary_Functions", "Exp"));
60
   ("pow",   ("Ada.Numerics.Elementary_Functions", "**"));
61
   ("sin",   ("Ada.Numerics.Elementary_Functions", "Sin"));
62
   ("cos",   ("Ada.Numerics.Elementary_Functions", "Cos"));
63
   ("tan",   ("Ada.Numerics.Elementary_Functions", "Tan"));
64
   ("asin",  ("Ada.Numerics.Elementary_Functions", "Arcsin"));
65
   ("acos",  ("Ada.Numerics.Elementary_Functions", "Arccos"));
66
   ("atan",  ("Ada.Numerics.Elementary_Functions", "Arctan"));
67
   ("sinh",  ("Ada.Numerics.Elementary_Functions", "Sinh"));
68
   ("cosh",  ("Ada.Numerics.Elementary_Functions", "Cosh"));
69
   ("tanh",  ("Ada.Numerics.Elementary_Functions", "Tanh"));
70
   ("asinh", ("Ada.Numerics.Elementary_Functions", "Arcsinh"));
71
   ("acosh", ("Ada.Numerics.Elementary_Functions", "Arccosh"));
72
   ("atanh", ("Ada.Numerics.Elementary_Functions", "Arctanh"));
73
   
74
   ("ceil",  ("", "Float'Ceiling"));
75
   ("floor", ("", "Float'Floor"));
76
   ("fmod",  ("", "Float'Remainder"));
77
   ("round", ("", "Float'Rounding"));
78
   ("trunc", ("", "Float'Truncation"));
79

    
80
   ("fabs", ("", "abs"));]
81

    
82
let is_builtin_fun ident =
83
  List.mem ident Basic_library.internal_funs ||
84
    List.mem_assoc ident ada_supported_funs
85

    
86
(** Print the name of a package associated to a machine.
87
   @param fmt the formater to print on
88
   @param machine the machine
89
**)
90
let pp_package_name machine fmt =
91
  if is_arrow machine then
92
      fprintf fmt "%t" pp_arrow_package_name
93
  else
94
      fprintf fmt "%a" pp_clean_ada_identifier machine.mname.node_id
95

    
96
(** Print a type.
97
   @param fmt the formater to print on
98
   @param type the type
99
**)
100
let pp_type fmt typ = 
101
  (match (Types.repr typ).Types.tdesc with
102
    | Types.Tbasic Types.Basic.Tint  -> pp_integer_type fmt
103
    | Types.Tbasic Types.Basic.Treal -> pp_float_type fmt
104
    | Types.Tbasic Types.Basic.Tbool -> pp_boolean_type fmt
105
    | Types.Tunivar                  -> pp_polymorphic_type typ.Types.tid fmt
106
    | Types.Tbasic _                 -> eprintf "Tbasic@."; assert false (*TODO*)
107
    | Types.Tconst _                 -> eprintf "Tconst@."; assert false (*TODO*)
108
    | Types.Tclock _                 -> eprintf "Tclock@."; assert false (*TODO*)
109
    | Types.Tarrow _                 -> eprintf "Tarrow@."; assert false (*TODO*)
110
    | Types.Ttuple l                 -> eprintf "Ttuple %a @." (Utils.fprintf_list ~sep:" " Types.print_ty) l; assert false (*TODO*)
111
    | Types.Tenum _                  -> eprintf "Tenum@.";  assert false (*TODO*)
112
    | Types.Tstruct _                -> eprintf "Tstruct@.";assert false (*TODO*)
113
    | Types.Tarray _                 -> eprintf "Tarray@."; assert false (*TODO*)
114
    | Types.Tstatic _                -> eprintf "Tstatic@.";assert false (*TODO*)
115
    | Types.Tlink _                  -> eprintf "Tlink@.";  assert false (*TODO*)
116
    | Types.Tvar                     -> eprintf "Tvar@.";   assert false (*TODO*)
117
    (*| _ -> eprintf "Type error : %a@." Types.print_ty typ; assert false *)
118
  )
119

    
120
(** Return a default ada constant for a given type.
121
   @param cst_typ the constant type
122
**)
123
let default_ada_cst cst_typ = match cst_typ with
124
  | Types.Basic.Tint  -> Const_int 0
125
  | Types.Basic.Treal -> Const_real (Num.num_of_int 0, 0, "0.0")
126
  | Types.Basic.Tbool -> Const_tag tag_false
127
  | _ -> assert false
128

    
129
(** Make a default value from a given type.
130
   @param typ the type
131
**)
132
let mk_default_value typ =
133
  match (Types.repr typ).Types.tdesc with
134
    | Types.Tbasic t  -> mk_val (Cst (default_ada_cst t)) typ
135
    | _                              -> assert false (*TODO*)
136

    
137
(** Print the type of a variable.
138
   @param fmt the formater to print on
139
   @param id the variable
140
**)
141
let pp_var_type fmt id = 
142
  pp_type fmt id.var_type
143

    
144
(** Print a package name with polymorphic types specified.
145
   @param substitution correspondance between polymorphic type id and their instantiation
146
   @param fmt the formater to print on
147
   @param machine the machine
148
**)
149
let pp_package_name_with_polymorphic substitution machine fmt =
150
  let polymorphic_types = find_all_polymorphic_type machine in
151
  assert(List.length polymorphic_types = List.length substitution);
152
  let substituion = List.sort_uniq (fun x y -> fst x - fst y) substitution in
153
  assert(List.for_all2 (fun poly1 (poly2, _) -> poly1 = poly2)
154
            polymorphic_types substituion);
155
  let instantiated_types = snd (List.split substitution) in
156
  fprintf fmt "%t%t%a"
157
    (pp_package_name machine)
158
    (Utils.pp_final_char_if_non_empty "_" instantiated_types)
159
    (Utils.fprintf_list ~sep:"_" pp_type) instantiated_types
160

    
161
(** Print the name of a variable.
162
   @param fmt the formater to print on
163
   @param id the variable
164
**)
165
let pp_var_name id fmt =
166
  fprintf fmt "%a" pp_clean_ada_identifier id.var_id
167

    
168
(** Print the complete name of variable.
169
   @param m the machine to check if it is memory
170
   @param fmt the formater to print on
171
   @param var the variable
172
**)
173
let pp_var env fmt var =
174
  match List.assoc_opt var.var_id env with
175
    | None -> pp_var_name var fmt
176
    | Some pp_state -> pp_access pp_state (pp_var_name var) fmt
177

    
178
(* Expression print functions *)
179

    
180
(* Printing functions for basic operations and expressions *)
181
(* TODO: refactor code -> use let rec and for basic pretty printing
182
   function *)
183
(** Printing function for Ada tags, mainly booleans.
184

    
185
    @param fmt the formater to use
186
    @param t the tag to print
187
 **)
188
let pp_ada_tag fmt t =
189
  pp_print_string fmt
190
    (if t = tag_true then "True" else if t = tag_false then "False" else t)
191

    
192
(** Printing function for machine type constants. For the moment,
193
    arrays are not supported.
194

    
195
    @param fmt the formater to use
196
    @param c the constant to print
197
 **)
198
let pp_ada_const fmt c =
199
  match c with
200
  | Const_int i                     -> pp_print_int fmt i
201
  | Const_real (c, e, s)            ->
202
      fprintf fmt "%s.0*1.0e-%i" (Num.string_of_num c) e
203
  | Const_tag t                     -> pp_ada_tag fmt t
204
  | Const_string _ | Const_modeid _ ->
205
    (Format.eprintf
206
       "internal error: Ada_backend_adb.pp_ada_const cannot print string or modeid.";
207
     assert false)
208
  | _                               ->
209
    raise (Ada_not_supported "unsupported: Ada_backend_adb.pp_ada_const does not
210
    support this constant")
211

    
212
(** Printing function for expressions [v1 modulo v2]. Depends
213
    on option [integer_div_euclidean] to choose between mathematical
214
    modulo or remainder ([rem] in Ada).
215

    
216
    @param pp_value pretty printer for values
217
    @param v1 the first value in the expression
218
    @param v2 the second value in the expression
219
    @param fmt the formater to print on
220
 **)
221
let pp_mod pp_value v1 v2 fmt =
222
  if !Options.integer_div_euclidean then
223
    (* (a rem b) + (a rem b < 0 ? abs(b) : 0) *)
224
    Format.fprintf fmt
225
      "((%a rem %a) + (if (%a rem %a) < 0 then abs(%a) else 0))"
226
      pp_value v1 pp_value v2
227
      pp_value v1 pp_value v2
228
      pp_value v2
229
  else (* Ada behavior for rem *)
230
    Format.fprintf fmt "(%a rem %a)" pp_value v1 pp_value v2
231

    
232
(** Printing function for expressions [v1 div v2]. Depends on
233
    option [integer_div_euclidean] to choose between mathematic
234
    division or Ada division.
235

    
236
    @param pp_value pretty printer for values
237
    @param v1 the first value in the expression
238
    @param v2 the second value in the expression
239
    @param fmt the formater to print in
240
 **)
241
let pp_div pp_value v1 v2 fmt =
242
  if !Options.integer_div_euclidean then
243
    (* (a - ((a rem b) + (if a rem b < 0 then abs (b) else 0))) / b) *)
244
    Format.fprintf fmt "(%a - %t) / %a"
245
      pp_value v1
246
      (pp_mod pp_value v1 v2)
247
      pp_value v2
248
  else (* Ada behavior for / *)
249
    Format.fprintf fmt "(%a / %a)" pp_value v1 pp_value v2
250

    
251
(** Printing function for basic lib functions.
252

    
253
    @param pp_value pretty printer for values
254
    @param i a string representing the function
255
    @param fmt the formater to print on
256
    @param vl the list of operands
257
 **)
258
let pp_basic_lib_fun pp_value ident fmt vl =
259
  match ident, vl with
260
  | "uminus", [v]    ->
261
    Format.fprintf fmt "(- %a)" pp_value v
262
  | "not", [v]       ->
263
    Format.fprintf fmt "(not %a)" pp_value v
264
  | "impl", [v1; v2] ->
265
    Format.fprintf fmt "(not %a or else %a)" pp_value v1 pp_value v2
266
  | "=", [v1; v2]    ->
267
    Format.fprintf fmt "(%a = %a)" pp_value v1 pp_value v2
268
  | "mod", [v1; v2]  -> pp_mod pp_value v1 v2 fmt
269
  | "equi", [v1; v2] ->
270
    Format.fprintf fmt "((not %a) = (not %a))" pp_value v1 pp_value v2
271
  | "xor", [v1; v2]  ->
272
    Format.fprintf fmt "((not %a) /= (not %a))" pp_value v1 pp_value v2
273
  | "/", [v1; v2]    -> pp_div pp_value v1 v2 fmt
274
  | "&&", [v1; v2]    ->
275
    Format.fprintf fmt "(%a %s %a)" pp_value v1 "and then" pp_value v2
276
  | "||", [v1; v2]    ->
277
    Format.fprintf fmt "(%a %s %a)" pp_value v1 "or else" pp_value v2
278
  | "!=", [v1; v2]    ->
279
    Format.fprintf fmt "(%a %s %a)" pp_value v1 "/=" pp_value v2
280
  | "ite", [v1; v2; v3]    ->
281
    Format.fprintf fmt "(if %a then %a else %a)" pp_value v1 pp_value v2 pp_value v3
282
  | op, [v1; v2]     ->
283
    Format.fprintf fmt "(%a %s %a)" pp_value v1 op pp_value v2
284
  | op, [v1] when  List.mem_assoc ident ada_supported_funs ->
285
    let pkg, name = try List.assoc ident ada_supported_funs
286
      with Not_found -> assert false in
287
    let pkg = pkg^(if String.equal pkg "" then "" else ".") in
288
      Format.fprintf fmt "%s%s(%a)" pkg name pp_value v1
289
  | fun_name, _      ->
290
    (Format.eprintf "internal compilation error: basic function %s@." fun_name; assert false)
291

    
292
(** Printing function for values.
293

    
294
    @param m the machine to know the state variable
295
    @param fmt the formater to use
296
    @param value the value to print. Should be a
297
           {!type:Machine_code_types.value_t} value
298
 **)
299
let rec pp_value env fmt value =
300
  match value.value_desc with
301
  | Cst c             -> pp_ada_const fmt c
302
  | Var var      -> pp_var env fmt var (* Find better to test if it is memory or not *)
303
  | Fun (f_ident, vl) -> pp_basic_lib_fun (pp_value env) f_ident fmt vl
304
  | _                 ->
305
    raise (Ada_not_supported
306
             "unsupported: Ada_backend.adb.pp_value does not support this value type")
307

    
308

    
309
(** Print the filename of a machine package.
310
   @param extension the extension to append to the package name
311
   @param fmt the formatter
312
   @param machine the machine corresponding to the package
313
**)
314
let pp_machine_filename extension fmt machine =
315
  pp_filename extension fmt (pp_package_name machine)
316

    
317
let pp_main_filename fmt _ = pp_filename "adb" fmt pp_main_procedure_name
318

    
319

    
320
(** Print the declaration of a state element of a subinstance of a machine.
321
   @param machine the machine
322
   @param fmt the formater to print on
323
   @param substitution correspondance between polymorphic type id and their instantiation
324
   @param ident the identifier of the subinstance
325
   @param submachine the submachine of the subinstance
326
**)
327
let build_pp_state_decl_from_subinstance mode with_statement (name, (substitution, machine)) =
328
  let pp_package = pp_package_name_with_polymorphic substitution machine in
329
  let pp_type = pp_package_access (pp_package, pp_state_type) in
330
  let pp_name fmt = pp_clean_ada_identifier fmt name in
331
  (mode, pp_name, pp_type, with_statement)
332

    
333
(** Print variable declaration for a local state variable
334
   @param fmt the formater to print on
335
   @param mode input/output mode of the parameter
336
**)
337
let build_pp_state_decl mode with_statement =
338
  (mode, pp_state_name, pp_state_type, with_statement)
339

    
340
let build_pp_var_decl mode with_statement var =
341
  let pp_name = function fmt -> pp_var_name var fmt in
342
  let pp_type = function fmt -> pp_var_type fmt var in
343
  (mode, pp_name, pp_type, with_statement)
344

    
345
let build_pp_var_decl_local with_statement var =
346
  AdaLocalVar (build_pp_var_decl AdaNoMode with_statement var)
347

    
348
let build_pp_var_decl_step_input mode with_statement m =
349
  if m.mstep.step_inputs=[] then [] else
350
    [List.map (build_pp_var_decl mode with_statement) m.mstep.step_inputs]
351

    
352
let build_pp_var_decl_step_output mode with_statement m =
353
  if m.mstep.step_outputs=[] then [] else
354
    [List.map (build_pp_var_decl mode with_statement) m.mstep.step_outputs]
355

    
356
let build_pp_var_decl_static mode with_statement m =
357
  if m.mstatic=[] then [] else
358
    [List.map (build_pp_var_decl mode with_statement) m.mstatic]
359

    
360
let build_pp_arg_step m =
361
  (if is_machine_statefull m then [[build_pp_state_decl AdaInOut None]] else [])
362
    @ (build_pp_var_decl_step_input AdaIn None m)
363
    @ (build_pp_var_decl_step_output AdaOut None m)
364

    
365
let build_pp_arg_reset m =
366
  (if is_machine_statefull m then [[build_pp_state_decl AdaOut None]] else [])
367
    @ (build_pp_var_decl_static AdaIn None m)
368

    
369

    
370
let build_pp_arg_transition m =
371
  (if is_machine_statefull m then [[build_pp_state_decl AdaInOut None]] else [])
372
    @ (build_pp_var_decl_step_input AdaIn None m)
373
    @ (build_pp_var_decl_step_output AdaOut None m)
374

    
(6-6/12)