Project

General

Profile

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

    
97
(** Print the integer type name.
98
   @param fmt the formater to print on
99
**)
100
let pp_integer_type fmt = fprintf fmt "Integer"
101

    
102
(** Print the float type name.
103
   @param fmt the formater to print on
104
**)
105
let pp_float_type fmt = fprintf fmt "Float"
106

    
107
(** Print the boolean type name.
108
   @param fmt the formater to print on
109
**)
110
let pp_boolean_type fmt = fprintf fmt "Boolean"
111

    
112

    
113
(** Print a type.
114
   @param fmt the formater to print on
115
   @param type the type
116
**)
117
let pp_type fmt typ = 
118
  (match (Types.repr typ).Types.tdesc with
119
    | Types.Tbasic Types.Basic.Tint  -> pp_integer_type fmt
120
    | Types.Tbasic Types.Basic.Treal -> pp_float_type fmt
121
    | Types.Tbasic Types.Basic.Tbool -> pp_boolean_type fmt
122
    | Types.Tunivar                  -> pp_polymorphic_type typ.Types.tid fmt
123
    | Types.Tbasic _                 -> eprintf "Tbasic@."; assert false (*TODO*)
124
    | Types.Tconst _                 -> eprintf "Tconst@."; assert false (*TODO*)
125
    | Types.Tclock _                 -> eprintf "Tclock@."; assert false (*TODO*)
126
    | Types.Tarrow _                 -> eprintf "Tarrow@."; assert false (*TODO*)
127
    | Types.Ttuple l                 -> eprintf "Ttuple %a @." (Utils.fprintf_list ~sep:" " Types.print_ty) l; assert false (*TODO*)
128
    | Types.Tenum _                  -> eprintf "Tenum@.";  assert false (*TODO*)
129
    | Types.Tstruct _                -> eprintf "Tstruct@.";assert false (*TODO*)
130
    | Types.Tarray _                 -> eprintf "Tarray@."; assert false (*TODO*)
131
    | Types.Tstatic _                -> eprintf "Tstatic@.";assert false (*TODO*)
132
    | Types.Tlink _                  -> eprintf "Tlink@.";  assert false (*TODO*)
133
    | Types.Tvar                     -> eprintf "Tvar@.";   assert false (*TODO*)
134
    (*| _ -> eprintf "Type error : %a@." Types.print_ty typ; assert false *)
135
  )
136

    
137
(** Return a default ada constant for a given type.
138
   @param cst_typ the constant type
139
**)
140
let default_ada_cst cst_typ = match cst_typ with
141
  | Types.Basic.Tint  -> Const_int 0
142
  | Types.Basic.Treal -> Const_real (Num.num_of_int 0, 0, "0.0")
143
  | Types.Basic.Tbool -> Const_tag tag_false
144
  | _ -> assert false
145

    
146
(** Make a default value from a given type.
147
   @param typ the type
148
**)
149
let mk_default_value typ =
150
  match (Types.repr typ).Types.tdesc with
151
    | Types.Tbasic t  -> mk_val (Cst (default_ada_cst t)) typ
152
    | _                              -> assert false (*TODO*)
153

    
154
(** Print the type of a variable.
155
   @param fmt the formater to print on
156
   @param id the variable
157
**)
158
let pp_var_type fmt id = 
159
  pp_type fmt id.var_type
160

    
161
(** Print a package name with polymorphic types specified.
162
   @param substitution correspondance between polymorphic type id and their instantiation
163
   @param fmt the formater to print on
164
   @param machine the machine
165
**)
166
let pp_package_name_with_polymorphic substitution machine fmt =
167
  let polymorphic_types = find_all_polymorphic_type machine in
168
  assert(List.length polymorphic_types = List.length substitution);
169
  let substituion = List.sort_uniq (fun x y -> fst x - fst y) substitution in
170
  assert(List.for_all2 (fun poly1 (poly2, _) -> poly1 = poly2)
171
            polymorphic_types substituion);
172
  let instantiated_types = snd (List.split substitution) in
173
  fprintf fmt "%t%t%a"
174
    (pp_package_name machine)
175
    (Utils.pp_final_char_if_non_empty "_" instantiated_types)
176
    (Utils.fprintf_list ~sep:"_" pp_type) instantiated_types
177

    
178
(** Print the name of a variable.
179
   @param fmt the formater to print on
180
   @param id the variable
181
**)
182
let pp_var_name fmt id =
183
  fprintf fmt "%a" pp_clean_ada_identifier id.var_id
184

    
185
(** Print the complete name of variable.
186
   @param m the machine to check if it is memory
187
   @param fmt the formater to print on
188
   @param var the variable
189
**)
190
let pp_access_var m fmt var =
191
  if is_memory m var then
192
    fprintf fmt "%t.%a" pp_state_name pp_var_name var
193
  else
194
    pp_var_name fmt var
195

    
196

    
197
(* Expression print functions *)
198

    
199
(* Printing functions for basic operations and expressions *)
200
(* TODO: refactor code -> use let rec and for basic pretty printing
201
   function *)
202
(** Printing function for Ada tags, mainly booleans.
203

    
204
    @param fmt the formater to use
205
    @param t the tag to print
206
 **)
207
let pp_ada_tag fmt t =
208
  pp_print_string fmt
209
    (if t = tag_true then "True" else if t = tag_false then "False" else t)
210

    
211
(** Printing function for machine type constants. For the moment,
212
    arrays are not supported.
213

    
214
    @param fmt the formater to use
215
    @param c the constant to print
216
 **)
217
let pp_ada_const fmt c =
218
  match c with
219
  | Const_int i                     -> pp_print_int fmt i
220
  | Const_real (c, e, s)            ->
221
      fprintf fmt "%s.0*1.0e-%i" (Num.string_of_num c) e
222
  | Const_tag t                     -> pp_ada_tag fmt t
223
  | Const_string _ | Const_modeid _ ->
224
    (Format.eprintf
225
       "internal error: Ada_backend_adb.pp_ada_const cannot print string or modeid.";
226
     assert false)
227
  | _                               ->
228
    raise (Ada_not_supported "unsupported: Ada_backend_adb.pp_ada_const does not
229
    support this constant")
230

    
231
(** Printing function for expressions [v1 modulo v2]. Depends
232
    on option [integer_div_euclidean] to choose between mathematical
233
    modulo or remainder ([rem] in Ada).
234

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

    
251
(** Printing function for expressions [v1 div v2]. Depends on
252
    option [integer_div_euclidean] to choose between mathematic
253
    division or Ada division.
254

    
255
    @param pp_value pretty printer for values
256
    @param v1 the first value in the expression
257
    @param v2 the second value in the expression
258
    @param fmt the formater to print in
259
 **)
260
let pp_div pp_value v1 v2 fmt =
261
  if !Options.integer_div_euclidean then
262
    (* (a - ((a rem b) + (if a rem b < 0 then abs (b) else 0))) / b) *)
263
    Format.fprintf fmt "(%a - %t) / %a"
264
      pp_value v1
265
      (pp_mod pp_value v1 v2)
266
      pp_value v2
267
  else (* Ada behavior for / *)
268
    Format.fprintf fmt "(%a / %a)" pp_value v1 pp_value v2
269

    
270
(** Printing function for basic lib functions.
271

    
272
    @param pp_value pretty printer for values
273
    @param i a string representing the function
274
    @param fmt the formater to print on
275
    @param vl the list of operands
276
 **)
277
let pp_basic_lib_fun pp_value ident fmt vl =
278
  match ident, vl with
279
  | "uminus", [v]    ->
280
    Format.fprintf fmt "(- %a)" pp_value v
281
  | "not", [v]       ->
282
    Format.fprintf fmt "(not %a)" pp_value v
283
  | "impl", [v1; v2] ->
284
    Format.fprintf fmt "(not %a or else %a)" pp_value v1 pp_value v2
285
  | "=", [v1; v2]    ->
286
    Format.fprintf fmt "(%a = %a)" pp_value v1 pp_value v2
287
  | "mod", [v1; v2]  -> pp_mod pp_value v1 v2 fmt
288
  | "equi", [v1; v2] ->
289
    Format.fprintf fmt "((not %a) = (not %a))" pp_value v1 pp_value v2
290
  | "xor", [v1; v2]  ->
291
    Format.fprintf fmt "((not %a) /= (not %a))" pp_value v1 pp_value v2
292
  | "/", [v1; v2]    -> pp_div pp_value v1 v2 fmt
293
  | "&&", [v1; v2]    ->
294
    Format.fprintf fmt "(%a %s %a)" pp_value v1 "and then" pp_value v2
295
  | "||", [v1; v2]    ->
296
    Format.fprintf fmt "(%a %s %a)" pp_value v1 "or else" pp_value v2
297
  | "!=", [v1; v2]    ->
298
    Format.fprintf fmt "(%a %s %a)" pp_value v1 "/=" pp_value v2
299
  | op, [v1; v2]     ->
300
    Format.fprintf fmt "(%a %s %a)" pp_value v1 op pp_value v2
301
  | op, [v1] when  List.mem_assoc ident ada_supported_funs ->
302
    let pkg, name = try List.assoc ident ada_supported_funs
303
      with Not_found -> assert false in
304
    let pkg = pkg^(if String.equal pkg "" then "" else ".") in
305
      Format.fprintf fmt "%s%s(%a)" pkg name pp_value v1
306
  | fun_name, _      ->
307
    (Format.eprintf "internal compilation error: basic function %s@." fun_name; assert false)
308

    
309
(** Printing function for values.
310

    
311
    @param m the machine to know the state variable
312
    @param fmt the formater to use
313
    @param value the value to print. Should be a
314
           {!type:Machine_code_types.value_t} value
315
 **)
316
let rec pp_value m fmt value =
317
  match value.value_desc with
318
  | Cst c             -> pp_ada_const fmt c
319
  | Var var      -> pp_access_var m fmt var
320
  | Fun (f_ident, vl) -> pp_basic_lib_fun (pp_value m) f_ident fmt vl
321
  | _                 ->
322
    raise (Ada_not_supported
323
             "unsupported: Ada_backend.adb.pp_value does not support this value type")
324

    
325

    
326
(** Print the filename of a machine package.
327
   @param extension the extension to append to the package name
328
   @param fmt the formatter
329
   @param machine the machine corresponding to the package
330
**)
331
let pp_machine_filename extension fmt machine =
332
  pp_filename extension fmt (pp_package_name machine)
333

    
334
let pp_main_filename fmt _ = pp_filename "adb" fmt pp_main_procedure_name
335

    
336

    
337
(** Print the declaration of a state element of a subinstance of a machine.
338
   @param machine the machine
339
   @param fmt the formater to print on
340
   @param substitution correspondance between polymorphic type id and their instantiation
341
   @param ident the identifier of the subinstance
342
   @param submachine the submachine of the subinstance
343
**)
344
let build_pp_state_decl_from_subinstance (name, (substitution, machine)) =
345
  let pp_package = pp_package_name_with_polymorphic substitution machine in
346
  let pp_type = pp_package_access (pp_package, pp_state_type) in
347
  let pp_name fmt = pp_clean_ada_identifier fmt name in
348
  (AdaNoMode, pp_name, pp_type)
349

    
350
(** Print variable declaration for a local state variable
351
   @param fmt the formater to print on
352
   @param mode input/output mode of the parameter
353
**)
354
let build_pp_state_decl mode =
355
  (mode, pp_state_name, pp_state_type)
356

    
357
let build_pp_var_decl mode var =
358
  let pp_name = function fmt -> pp_var_name fmt var in
359
  let pp_type = function fmt -> pp_var_type fmt var in
360
  (mode, pp_name, pp_type)
361

    
362
let build_pp_var_decl_local var =
363
  AdaLocalVar (build_pp_var_decl AdaNoMode var)
364

    
365
let build_pp_var_decl_step_input mode m =
366
  if m.mstep.step_inputs=[] then [] else
367
    [List.map (build_pp_var_decl mode) m.mstep.step_inputs]
368

    
369
let build_pp_var_decl_step_output mode m =
370
  if m.mstep.step_outputs=[] then [] else
371
    [List.map (build_pp_var_decl mode) m.mstep.step_outputs]
372

    
373
let build_pp_var_decl_static mode m =
374
  if m.mstatic=[] then [] else
375
    [List.map (build_pp_var_decl mode) m.mstatic]
376

    
377
let build_pp_arg_step m =
378
  (if is_machine_statefull m then [[build_pp_state_decl AdaInOut]] else [])
379
    @ (build_pp_var_decl_step_input AdaIn m)
380
    @ (build_pp_var_decl_step_output AdaOut m)
381

    
382
let build_pp_arg_reset m =
383
  (if is_machine_statefull m then [[build_pp_state_decl AdaOut]] else [])
384
    @ (build_pp_var_decl_static AdaIn m)
(6-6/12)