Project

General

Profile

Statistics
| Branch: | Tag: | Revision:

lustrec / src / backends / EMF / EMF_common.ml @ ab8388cf

History | View | Annotate | Download (15.9 KB)

1
open Lustre_types
2
open Machine_code_types
3
module VSet = Corelang.VSet
4
open Format
5
open Machine_code_common
6

    
7
(* Matlab starting counting from 1.
8
   simple function to extract the element id in the list. Starts from 1. *)
9
let rec get_idx x l =
10
  match l with
11
  | hd::tl -> if hd = x then 1 else 1+(get_idx x tl)
12
  | [] -> assert false
13

    
14
let rec get_expr_vars v =
15
  match v.value_desc with
16
  | Cst c -> VSet.empty
17
  | Var v -> VSet.singleton v
18
  | Fun (_, args) -> List.fold_left (fun accu v -> VSet.union accu (get_expr_vars v)) VSet.empty args
19
  | _ -> assert false (* Invalid argument *)
20

    
21
let is_imported_node f m =
22
  let (decl, _) = List.assoc f m.mcalls in
23
  Corelang.is_imported_node decl
24

    
25
(* Handling of enumerated types: for the moment each of such type is transformed
26
   into an int: the idx number of the constant in the typedef. This is not so
27
   nice but is compatible with basic Simulink types: int, real, bools) *)
28
(*
29
let recorded_enums = ref []
30
let record_types prog =
31
  let typedefs = Corelang.get_typedefs prog in
32
  List.iter (fun top ->
33
    let consts = consts_of_enum_type top in
34
  ) prog
35
*)
36
    
37
(* Basic printing functions *)
38

    
39
let hash_map = Hashtbl.create 13
40
  
41
(* If string length of f is longer than 50 chars, we select the 10 first and
42
   last and put a hash in the middle *)
43
let print_protect fmt f =
44
  fprintf str_formatter "%t" f;
45
  let s = flush_str_formatter () in
46
  let l = String.length s in
47
  if l > 30 then
48
    (* let _ = Format.eprintf "Looking for variable %s in hash @[<v 0>%t@]@." *)
49
    (*   s *)
50
    (*   (fun fmt -> Hashtbl.iter (fun s new_s -> fprintf fmt "%s -> %s@ " s new_s) hash_map) *)
51
    (* in *)
52
    if Hashtbl.mem hash_map s then
53
    fprintf fmt "%s" (Hashtbl.find hash_map s)
54
    else
55
      let prefix = String.sub s 0 10 and
56
	  suffix = String.sub s (l-10) 10 in
57
      let hash = Hashtbl.hash s in
58
      fprintf str_formatter "%s_%i_%s" prefix hash suffix;
59
      let new_s = flush_str_formatter () in
60
      Hashtbl.add hash_map s new_s;
61
      fprintf fmt "%s" new_s
62
  else
63
    fprintf fmt "%s" s
64
    
65
let pp_var_string fmt v =fprintf fmt "\"%t\"" (fun fmt -> print_protect fmt (fun fmt -> fprintf fmt "%s" v)) 
66
let pp_var_name fmt v = print_protect fmt (fun fmt -> Printers.pp_var_name fmt v) 
67
(*let pp_node_args = fprintf_list ~sep:", " pp_var_name*)
68

    
69
(********* Printing types ***********)
70
(* Two cases:
71
   - printing a variable definition:
72
     -  we look at the declared type if available
73
     - if not, we print the inferred type
74

    
75
   - printing a constant definion
76
*)
77
  
78
  
79

    
80
let rec pp_emf_dim fmt dim_expr =
81
  fprintf fmt "{";
82
  (let open Dimension in
83
   match dim_expr.dim_desc with
84
   | Dbool b -> fprintf fmt "\"kind\": \"bool\",@ \"value\": \"%b\"" b
85
   | Dint i -> fprintf fmt "\"kind\": \"int\",@ \"value\": \"%i\"" i
86
   | Dident s -> fprintf fmt "\"kind\": \"ident\",@ \"value\": \"%s\"" s
87
   | Dappl(f, args) -> fprintf fmt "\"kind\": \"fun\",@ \"id\": \"%s\",@ \"args\": [@[%a@]]"
88
                         f (Utils.fprintf_list ~sep:",@ " pp_emf_dim) args 
89
   | Dite(i,t,e) -> fprintf fmt "\"kind\": \"ite\",@ \"guard\": \"%a\",@ \"then\": %a,@ \"else\": %a"
90
                      pp_emf_dim i pp_emf_dim t pp_emf_dim e 
91
   | Dlink e -> pp_emf_dim fmt e
92
   | Dvar
93
   | Dunivar -> assert false (* unresolved *)
94
  );
95
  fprintf fmt "}"
96

    
97
     
98

    
99

    
100
(* First try to print the declared one *)
101
let rec pp_concrete_type dec_t infered_t fmt =
102
  match dec_t with
103
  | Tydec_any -> (* Dynamical built variable. No declared type. Shall
104
                    use the infered one. *)
105
     pp_infered_type fmt infered_t
106
  | Tydec_int -> fprintf fmt "{ \"kind\": \"int\" }" (* !Options.int_type *)
107
  | Tydec_real -> fprintf fmt "{ \"kind\": \"real\" }" (* !Options.real_type *)
108
  (* TODO we could add more concrete types here if they were available in
109
     dec_t *)
110
  | Tydec_bool -> fprintf fmt "{ \"kind\": \"bool\" }"
111
  | Tydec_clock t -> pp_concrete_type t infered_t fmt
112
  | Tydec_const id -> (
113
    (* This is an alias type *)
114

    
115
    (* id for a enumerated type, eg. introduced by automata *)
116
    let typ = (Corelang.typedef_of_top (Hashtbl.find Corelang.type_table dec_t)) in
117
    (* Print the type name associated to this enumerated type. This is
118
       basically an integer *)
119
    pp_tag_type id typ infered_t fmt
120
  )
121
                    
122
  | Tydec_struct _ | Tydec_enum _ ->
123
     assert false (* should not happen. These type are only built when
124
                     declaring a type in the prefix of the lustre
125
                     file. They shall not be associated to variables
126
                   *)
127
    
128
  | Tydec_array (dim, e) -> (
129
    let inf_base = match infered_t.Typing.tdesc with
130
      | Typing.Tarray(_,t) -> t
131
      | _ ->   (* returing something useless, hoping that the concrete
132
                  datatype will return something usefull *)
133
         Typing.new_var ()
134
    in
135
    fprintf fmt "{ \"kind\": \"array\", \"base_type\": %t, \"dim\": %a }"
136
      (pp_concrete_type e inf_base)
137
      pp_emf_dim dim
138
  )
139
                          
140
(* | _ -> eprintf
141
 *          "unhandled construct in type printing for EMF backend: %a@."
142
 *          Printers.pp_var_type_dec_desc dec_t; raise (Failure "var") *)
143
and pp_tag_type id typ inf fmt =
144
  (* We ought to represent these types as values: enum will become int, we keep the name for structs *)
145
  let rec aux tydec_desc =
146
    match tydec_desc with  
147
    | Tydec_int 
148
      | Tydec_real 
149
      | Tydec_bool
150
      | Tydec_array _ -> pp_concrete_type tydec_desc inf fmt
151
    | Tydec_const id ->
152
       (* Alias of an alias: unrolling definitions *)
153
       let typ = (Corelang.typedef_of_top
154
                    (Hashtbl.find Corelang.type_table tydec_desc))
155
       in
156
       pp_tag_type id typ inf fmt
157
       
158
    | Tydec_clock ty -> aux ty
159
    | Tydec_enum const_list -> ( (* enum can be mapped to int *)
160
      let size = List.length const_list in
161
      fprintf fmt "{ \"name\": \"%s\", \"kind\": \"enum\", \"size\": \"%i\" }" id size
162
    )
163
    | Tydec_struct _ ->
164
       fprintf fmt "{ \"name\": \"%s\", \"kind\": \"struct\" }" id
165
    | Tydec_any -> (* shall not happen: a declared type cannot be
166
                      bound to type any *)
167
       assert false
168
  in
169
  aux typ.tydef_desc
170
and pp_infered_type fmt t =
171
  (* Shall only be used for variable types that were not properly declared. Ie generated at compile time. *)
172
  let open Types in
173
  if is_bool_type t  then fprintf fmt "{ \"kind\": \"bool\" }" else
174
    if is_int_type t then fprintf fmt "{ \"kind\": \"int\" }" else (* !Options.int_type *)
175
      if is_real_type t then fprintf fmt "{ \"kind\": \"real\" }" else (* !Options.real_type *)
176
        match t.tdesc with
177
        | Tclock t ->
178
           pp_infered_type fmt t
179
        | Tstatic (_, t) ->
180
           fprintf fmt "%a" pp_infered_type t
181
        | Tconst id ->
182
           (* This is a type id for a enumerated type, eg. introduced by automata *)
183
           let typ =
184
             (Corelang.typedef_of_top
185
                (Hashtbl.find Corelang.type_table (Tydec_const id)))
186
           in
187
           pp_tag_type id typ t fmt
188
        | Tlink ty -> 
189
           pp_infered_type fmt ty
190
        | Tarray (dim, base_t) ->
191
           fprintf fmt "{ \"kind\": \"array\", \"base_type\": %a, \"dim\": %a }"
192
             pp_infered_type base_t
193
             pp_emf_dim dim
194
    | _ -> eprintf "unhandled type: %a@." Types.print_node_ty t; assert false
195

    
196
(*let pp_cst_type fmt v =
197
  match v.value_desc with
198
  | Cst c-> pp_cst_type c v.value_type fmt (* constants do not have declared type (yet) *)
199
  | _ -> assert false
200
*)
201

    
202
(* Provide both the declared type and the infered one. *)
203
let pp_var_type fmt v =
204
  try
205
    if Machine_types.is_specified v then
206
      Machine_types.pp_var_type fmt v
207
    else
208
      pp_concrete_type v.var_dec_type.ty_dec_desc v.var_type fmt
209
  with Failure msg -> eprintf "failed var: %a@.%s@." Printers.pp_var v msg; assert false
210
    
211
(******** Other print functions *)
212

    
213
let pp_emf_list ?(eol:('a, formatter, unit) Pervasives.format="") pp fmt l =
214
  match l with
215
    [] -> ()
216
  | _ -> fprintf fmt "@[";
217
         Utils.fprintf_list ~sep:",@ " pp fmt l;
218
         fprintf fmt "@]%(%)" eol
219
  
220
(* Print the variable declaration *)
221
let pp_emf_var_decl fmt v =
222
  fprintf fmt "@[{\"name\": \"%a\", \"datatype\": %a, \"original_name\": \"%a\"}@]"
223
    pp_var_name v
224
    pp_var_type v
225
    Printers.pp_var_name v
226

    
227
let pp_emf_vars_decl = pp_emf_list pp_emf_var_decl
228

    
229
 
230
  
231
let reset_name id =
232
  "reset_" ^ id
233
  
234
let pp_tag_id fmt t =
235
  let typ = (Corelang.typedef_of_top (Hashtbl.find Corelang.tag_table t)) in
236
  if typ.tydef_id = "bool" then
237
    pp_print_string fmt t
238
  else
239
    let const_list = match typ.tydef_desc with Tydec_enum tl -> tl | _ -> assert false in
240
    fprintf fmt "%i" (get_idx t const_list)
241

    
242
let pp_cst_type c inf fmt (*infered_typ*) =
243
  let pp_basic fmt s = fprintf fmt "{ \"kind\": \"%s\" }" s in
244
  match c with
245
  | Const_tag t ->
246
     let typ = (Corelang.typedef_of_top (Hashtbl.find Corelang.tag_table t)) in
247
     if typ.tydef_id = "bool" then
248
       pp_basic fmt "bool"
249
     else
250
       pp_tag_type t typ inf fmt
251
  | Const_int _ -> pp_basic fmt "int" (*!Options.int_type*)
252
  | Const_real _ -> pp_basic fmt "real" (*!Options.real_type*)
253
  | Const_string _ -> pp_basic fmt "string" 
254
  | _ -> eprintf "cst: %a@." Printers.pp_const c; assert false
255

    
256
    
257
let pp_emf_cst c inf fmt =
258
  let pp_typ fmt = 
259
    fprintf fmt "\"datatype\": %t@ "
260
      (pp_cst_type c inf)   
261
  in
262
  match c with
263
  | Const_tag t->
264
     let typ = (Corelang.typedef_of_top (Hashtbl.find Corelang.tag_table t)) in
265
     if typ.tydef_id = "bool" then (
266
       fprintf fmt "{@[\"type\": \"constant\",@ ";
267
       fprintf fmt"\"value\": \"%a\",@ "
268
	 Printers.pp_const c;
269
       pp_typ fmt;
270
       fprintf fmt "@]}"
271
     )
272
     else (
273
       fprintf fmt "{@[\"type\": \"constant\",@ \"value\": \"%a\",@ " 
274
	 pp_tag_id t;
275
       fprintf fmt "\"origin_type\": \"%s\",@ \"origin_value\": \"%s\",@ "
276
	 typ.tydef_id t;
277
       pp_typ fmt;
278
       fprintf fmt "@]}"
279
     )
280
  | Const_string s ->
281
     fprintf fmt "{@[\"type\": \"constant\",@ \"value\": \"%s\",@ " s;
282
     pp_typ fmt;
283
     fprintf fmt "@]}"
284
     
285
  | _ -> (
286
    fprintf fmt "{@[\"type\": \"constant\",@ \"value\": \"%a\",@ "
287
      Printers.pp_const c;
288
    pp_typ fmt;
289
    fprintf fmt "@]}"
290
  )
291
  
292
(* Print a value: either a constant or a variable value *)
293
let rec pp_emf_cst_or_var m fmt v =
294
  match v.value_desc with
295
  | Cst c -> pp_emf_cst c v.value_type fmt 
296
  | Var v -> (
297
    fprintf fmt "{@[\"type\": \"variable\",@ \"value\": \"%a\",@ "
298
      pp_var_name v;
299
    (*    fprintf fmt "\"original_name\": \"%a\",@ " Printers.pp_var_name v; *)
300
    fprintf fmt "\"datatype\": %a@ " pp_var_type v;
301
    fprintf fmt "@]}"
302
  )
303
  | Array vl -> (
304
     fprintf fmt "{@[\"type\": \"array\",@ \"value\": @[[%a@]],@ "
305
      (pp_emf_cst_or_var_list m) vl;
306
     fprintf fmt "@]}"
307
  )
308
  | Access (arr, idx) -> (
309
      fprintf fmt "{@[\"type\": \"array access\",@ \"array\": @[[%a@]],@ \"idx\": @[[%a@]],@ "
310
      (pp_emf_cst_or_var m) arr (pp_emf_cst_or_var m) idx;
311
     fprintf fmt "@]}"
312
  )
313
  | Power (v,nb) ->(
314
      fprintf fmt "{@[\"type\": \"power\",@ \"expr\": @[[%a@]],@ \"nb\": @[[%a@]],@ "
315
      (pp_emf_cst_or_var m) v (pp_emf_cst_or_var m) nb;
316
     fprintf fmt "@]}"
317
  )
318
  | Fun _ -> eprintf "Fun expression should have been normalized: %a@." (pp_val m) v ; assert false (* Invalid argument *)
319

    
320
and pp_emf_cst_or_var_list m =
321
  Utils.fprintf_list ~sep:",@ " (pp_emf_cst_or_var m)
322

    
323
(* Printer lustre expr and eexpr *)
324
    
325
let rec pp_emf_expr fmt e =
326
  match e.expr_desc with
327
  | Expr_const c -> pp_emf_cst c e.expr_type fmt 
328
  | Expr_ident id ->
329
     fprintf fmt "{@[\"type\": \"variable\",@ \"value\": \"%a\",@ "
330
       print_protect (fun fmt -> pp_print_string fmt id);
331
    fprintf fmt "\"datatype\": %t@ "
332
      (pp_concrete_type
333
	 Tydec_any (* don't know much about that time since it was not
334
		      declared. That may not work with clock constants *)
335
	 e.expr_type
336
      );
337
    fprintf fmt "@]}"
338

    
339
  | Expr_tuple el ->
340
     fprintf fmt "[@[<hov 0>%a@ @]]"
341
       (Utils.fprintf_list ~sep:",@ " pp_emf_expr) el
342
 (* Missing these 
343
  | Expr_ite   of expr * expr * expr
344
  | Expr_arrow of expr * expr
345
  | Expr_fby of expr * expr
346
  | Expr_array of expr list
347
  | Expr_access of expr * Dimension.dim_expr
348
  | Expr_power of expr * Dimension.dim_expr
349
  | Expr_pre of expr
350
  | Expr_when of expr * ident * label
351
  | Expr_merge of ident * (label * expr) list
352
  | Expr_appl of call_t
353
  *)
354
  | _ -> (
355
    Log.report ~level:2
356
      (fun fmt ->
357
	fprintf fmt "Warning: unhandled expression %a in annotation.@ "
358
	  Printers.pp_expr e;
359
 	fprintf fmt "Will not be produced in the experted JSON EMF@."
360
      );    
361
    fprintf fmt "\"unhandled construct, complain to Ploc\""
362
  )
363
(* Remaining constructs *)  
364
(* | Expr_ite   of expr * expr * expr *)
365
(* | Expr_arrow of expr * expr *)
366
(* | Expr_fby of expr * expr *)
367
(* | Expr_array of expr list *)
368
(* | Expr_access of expr * Dimension.dim_expr *)
369
(* | Expr_power of expr * Dimension.dim_expr *)
370
(* | Expr_pre of expr *)
371
(* | Expr_when of expr * ident * label *)
372
(* | Expr_merge of ident * (label * expr) list *)
373
(* | Expr_appl of call_t *)
374

    
375
let pp_emf_exprs = pp_emf_list pp_emf_expr
376
       
377
let pp_emf_const fmt v =
378
  fprintf fmt "@[<hov 0>{\"name\": \"%a\",@ \"datatype\":%a,@ \"original_name\": \"%a\",@ \"value\": %a}@]"
379
    pp_var_name v
380
    pp_var_type v
381
    Printers.pp_var_name v
382
    pp_emf_expr (match v.var_dec_value with None -> assert false | Some e -> e)
383

    
384
let pp_emf_consts = pp_emf_list pp_emf_const
385
                  
386
let pp_emf_eexpr fmt ee =
387
  fprintf fmt "{@[<hov 0>%t\"quantifiers\": \"%a\",@ \"qfexpr\": @[%a@]@] }"
388
    (fun fmt -> match ee.eexpr_name with
389
                | None -> ()
390
                | Some name -> Format.fprintf fmt "\"name\": \"%s\",@ " name
391
    )
392
    (Utils.fprintf_list ~sep:"; " Printers.pp_quantifiers)
393
    ee.eexpr_quantifiers
394
    pp_emf_expr ee.eexpr_qfexpr
395

    
396
let pp_emf_eexprs = pp_emf_list pp_emf_eexpr
397

    
398
(*
399
                      TODO Thanksgiving
400

    
401
                      trouver un moyen de transformer en machine code les instructions de chaque spec
402
                      peut etre associer a chaque imported node une minimachine
403
                      et rajouter un champ a spec dans machine code pour stoquer memoire et instr
404
 *)                
405
                 
406
let pp_emf_stmt fmt stmt =
407
  match stmt with
408
  | Aut _ -> assert false
409
  | Eq eq -> (
410
    fprintf fmt "@[ @[<v 2>\"%a\": {@ " (Utils.fprintf_list ~sep:"_" pp_print_string) eq.eq_lhs;
411
    fprintf fmt "\"lhs\": [%a],@ " (Utils.fprintf_list ~sep:", " (fun fmt vid -> fprintf fmt "\"%s\"" vid)) eq.eq_lhs;
412
    fprintf fmt "\"rhs\": %a,@ " pp_emf_expr eq.eq_rhs;
413
    fprintf fmt "@]@]@ }"
414
  )
415

    
416
let pp_emf_stmts = pp_emf_list pp_emf_stmt 
417
  
418
(* Printing the type declaration, not its use *)
419
let rec pp_emf_typ_dec fmt tydef_dec =
420
  fprintf fmt "{";
421
  (match tydef_dec with
422
   | Tydec_any -> fprintf fmt "\"kind\": \"any\""
423
   | Tydec_int -> fprintf fmt "\"kind\": \"int\""
424
   | Tydec_real -> fprintf fmt "\"kind\": \"real\""
425
   | Tydec_bool-> fprintf fmt "\"kind\": \"bool\""
426
   | Tydec_clock ck -> pp_emf_typ_dec fmt ck
427
   | Tydec_const c -> fprintf fmt "\"kind\": \"alias\",@ \"value\": \"%s\"" c
428
   | Tydec_enum el -> fprintf fmt "\"kind\": \"enum\",@ \"elements\": [%a]"
429
                        (Utils.fprintf_list ~sep:", " (fun fmt e -> fprintf fmt "\"%s\"" e)) el
430
   | Tydec_struct s -> fprintf fmt "\"kind\": \"struct\",@ \"fields\": [%a]"
431
                         (Utils.fprintf_list ~sep:", " (fun fmt (id,typ) ->
432
                              fprintf fmt "\"%s\": %a" id pp_emf_typ_dec typ)) s
433
   | Tydec_array (dim, typ) -> fprintf fmt "\"kind\": \"array\",@ \"dim\": @[%a@],@ \"base\": %a"
434
                               pp_emf_dim dim
435
                               pp_emf_typ_dec typ
436
  );
437
  fprintf fmt "}"
438
 
439
let pp_emf_typedef fmt typdef_top =
440
  let typedef = Corelang.typedef_of_top typdef_top in
441
  fprintf fmt "{ \"%s\": @[%a@] }" typedef.tydef_id pp_emf_typ_dec typedef.tydef_desc 
442
  
443
let pp_emf_top_const fmt const_top = 
444
  let const = Corelang.const_of_top const_top in
445
  fprintf fmt "{ \"%s\": %t }"
446
    const.const_id
447
    (pp_emf_cst const.const_value const.const_type)
448

    
449
(* Local Variables: *)
450
(* compile-command: "make -C ../.." *)
451
(* End: *)