lustrec / src / backends / EMF / EMF_common.ml @ 785b64f9
History | View | Annotate | Download (6.38 KB)
1 |
open LustreSpec |
---|---|
2 |
open Format |
3 |
open Machine_code |
4 |
|
5 |
(* Matlab starting counting from 1. |
6 |
simple function to extract the element id in the list. Starts from 1. *) |
7 |
let rec get_idx x l = |
8 |
match l with |
9 |
| hd::tl -> if hd = x then 1 else 1+(get_idx x tl) |
10 |
| [] -> assert false |
11 |
|
12 |
let rec get_expr_vars v = |
13 |
match v.value_desc with |
14 |
| Cst c -> VSet.empty |
15 |
| LocalVar v | StateVar v -> VSet.singleton v |
16 |
| Fun (_, args) -> List.fold_left (fun accu v -> VSet.union accu (get_expr_vars v)) VSet.empty args |
17 |
| _ -> assert false (* Invalid argument *) |
18 |
|
19 |
let is_imported_node f m = |
20 |
let (decl, _) = List.assoc f m.mcalls in |
21 |
Corelang.is_imported_node decl |
22 |
|
23 |
(* Handling of enumerated types: for the moment each of such type is transformed |
24 |
into an int: the idx number of the constant in the typedef. This is not so |
25 |
nice but is compatible with basic Simulink types: int, real, bools) *) |
26 |
(* |
27 |
let recorded_enums = ref [] |
28 |
let record_types prog = |
29 |
let typedefs = Corelang.get_typedefs prog in |
30 |
List.iter (fun top -> |
31 |
let consts = consts_of_enum_type top in |
32 |
) prog |
33 |
*) |
34 |
|
35 |
(* Basic printing functions *) |
36 |
|
37 |
(* If string length of f is longer than 50 chars, we select the 20 first and |
38 |
last and put a hash in the middle *) |
39 |
let print_protect fmt f = |
40 |
fprintf str_formatter "%t" f; |
41 |
let s = flush_str_formatter () in |
42 |
let l = String.length s in |
43 |
if l > 50 then |
44 |
let prefix = String.sub s 0 20 and |
45 |
suffix = String.sub s (l-20) 20 in |
46 |
let hash = Hashtbl.hash s in |
47 |
fprintf fmt "%s_%i_%s" prefix hash suffix |
48 |
else |
49 |
fprintf fmt "%s" s |
50 |
|
51 |
let pp_var_string fmt v = fprintf fmt "\"%s\"" v |
52 |
let pp_var_name fmt v = print_protect fmt (fun fmt -> Printers.pp_var_name fmt v) |
53 |
(*let pp_node_args = fprintf_list ~sep:", " pp_var_name*) |
54 |
|
55 |
(********* Printing types ***********) |
56 |
(* Two cases: |
57 |
- printing a variable definition: |
58 |
- we look at the declared type if available |
59 |
- if not, we print the inferred type |
60 |
|
61 |
- printing a constant definion |
62 |
*) |
63 |
|
64 |
|
65 |
let pp_tag_type fmt typ = |
66 |
let const_list = match typ.tydef_desc with Tydec_enum tl -> tl | _ -> assert false in |
67 |
let size = List.length const_list in |
68 |
if size < 255 then |
69 |
fprintf fmt "uint8" |
70 |
else if size < 65535 then |
71 |
fprintf fmt "uint16" |
72 |
else |
73 |
assert false (* Too much states. This not reasonable *) |
74 |
|
75 |
|
76 |
|
77 |
let pp_cst_type c infered_typ fmt = |
78 |
match c with |
79 |
| Const_tag t -> |
80 |
let typ = (Corelang.typedef_of_top (Hashtbl.find Corelang.tag_table t)) in |
81 |
if typ.tydef_id = "bool" then |
82 |
fprintf fmt "bool" |
83 |
else |
84 |
pp_tag_type fmt typ |
85 |
| Const_int _ -> fprintf fmt "%s" !Options.int_type |
86 |
| Const_real _ -> fprintf fmt "%s" !Options.real_type |
87 |
| _ -> Format.eprintf "cst: %a@." Printers.pp_const c; assert false |
88 |
|
89 |
let rec pp_infered_type fmt t = |
90 |
let open Types in |
91 |
match t.tdesc with |
92 |
| Tint -> |
93 |
fprintf fmt "%s" !Options.int_type |
94 |
| Treal -> |
95 |
fprintf fmt "%s" !Options.real_type |
96 |
| Tbool -> |
97 |
fprintf fmt "bool" |
98 |
| Tclock t -> |
99 |
pp_infered_type fmt t |
100 |
| Tstatic (_, t) -> |
101 |
fprintf fmt "%a" pp_infered_type t |
102 |
| Tconst id -> |
103 |
(* This is a type id for a enumerated type, eg. introduced by automata *) |
104 |
let typ = |
105 |
(Corelang.typedef_of_top (Hashtbl.find Corelang.type_table (Tydec_const id))) |
106 |
in |
107 |
pp_tag_type fmt typ |
108 |
| Tlink ty -> |
109 |
pp_infered_type fmt ty |
110 |
| _ -> Format.eprintf "unhandled type: %a@." Types.print_node_ty t; assert false |
111 |
let rec pp_concrete_type dec_t infered_t fmt = |
112 |
match dec_t with |
113 |
| Tydec_int -> fprintf fmt "%s" !Options.int_type |
114 |
| Tydec_real -> fprintf fmt "%s" !Options.real_type |
115 |
(* TODO we could add more concrete types here if they were available in |
116 |
dec_t *) |
117 |
| Tydec_bool -> fprintf fmt "bool" |
118 |
| Tydec_clock t -> pp_concrete_type t infered_t fmt |
119 |
| Tydec_const id -> ( |
120 |
(* This is a type id for a enumerated type, eg. introduced by automata *) |
121 |
let typ = (Corelang.typedef_of_top (Hashtbl.find Corelang.type_table dec_t)) in |
122 |
pp_tag_type fmt typ |
123 |
) |
124 |
| Tydec_any -> pp_infered_type fmt infered_t |
125 |
| _ -> Format.eprintf |
126 |
"unhandled construct in type printing for EMF backend: %a@." |
127 |
Printers.pp_var_type_dec_desc dec_t; raise (Failure "var") |
128 |
|
129 |
|
130 |
let pp_cst_type fmt v = |
131 |
match v.value_desc with |
132 |
| Cst c-> pp_cst_type c v.value_type fmt (* constants do not have declared type (yet) *) |
133 |
| _ -> assert false |
134 |
|
135 |
let pp_var_type fmt v = |
136 |
try |
137 |
pp_concrete_type v.var_dec_type.ty_dec_desc v.var_type fmt |
138 |
with Failure _ -> Format.eprintf "failed var: %a@." Printers.pp_var v; assert false |
139 |
(******** Other print functions *) |
140 |
|
141 |
let pp_emf_var_decl fmt v = |
142 |
fprintf fmt "@[{\"name\": \"%a\", \"datatype\":\"%a\"}@]" |
143 |
pp_var_name v |
144 |
pp_var_type v |
145 |
|
146 |
let pp_emf_vars_decl fmt vl = |
147 |
fprintf fmt "@["; |
148 |
Utils.fprintf_list ~sep:",@ " pp_emf_var_decl fmt vl; |
149 |
fprintf fmt "@]" |
150 |
|
151 |
let reset_name id = |
152 |
"reset_" ^ id |
153 |
|
154 |
let pp_tag_id fmt t = |
155 |
let typ = (Corelang.typedef_of_top (Hashtbl.find Corelang.tag_table t)) in |
156 |
if typ.tydef_id = "bool" then |
157 |
pp_print_string fmt t |
158 |
else |
159 |
let const_list = match typ.tydef_desc with Tydec_enum tl -> tl | _ -> assert false in |
160 |
fprintf fmt "%i" (get_idx t const_list) |
161 |
|
162 |
let pp_emf_cst_or_var fmt v = |
163 |
match v.value_desc with |
164 |
| Cst ((Const_tag t) as c)-> |
165 |
let typ = (Corelang.typedef_of_top (Hashtbl.find Corelang.tag_table t)) in |
166 |
if typ.tydef_id = "bool" then ( |
167 |
fprintf fmt "{@[\"type\": \"constant\",@ "; |
168 |
fprintf fmt"\"value\": \"%a\",@ " |
169 |
Printers.pp_const c; |
170 |
fprintf fmt "\"datatype\": \"%a\"@ " pp_cst_type v; |
171 |
fprintf fmt "@]}" |
172 |
) |
173 |
else ( |
174 |
fprintf fmt "{@[\"type\": \"constant\",@ \"value\": \"%a\",@ " |
175 |
pp_tag_id t; |
176 |
fprintf fmt "\"origin_type\": \"%s\",@ \"origin_value\": \"%s\",@ " |
177 |
typ.tydef_id t; |
178 |
fprintf fmt "\"datatype\": \"%a\"@ " pp_cst_type v; |
179 |
fprintf fmt "@]}" |
180 |
) |
181 |
| Cst c -> ( |
182 |
fprintf fmt "{@[\"type\": \"constant\",@ \"value\": \"%a\",@ " |
183 |
Printers.pp_const c; |
184 |
fprintf fmt "\"datatype\": \"%a\"@ " pp_cst_type v; |
185 |
fprintf fmt "@]}" |
186 |
) |
187 |
| LocalVar v |
188 |
| StateVar v -> ( |
189 |
fprintf fmt "{@[\"type\": \"variable\",@ \"value\": \"%a\",@ " |
190 |
Printers.pp_var_name v; |
191 |
fprintf fmt "\"datatype\": \"%a\"@ " pp_var_type v; |
192 |
fprintf fmt "@]}" |
193 |
) |
194 |
| _ -> Format.eprintf "Not of cst or var: %a@." Machine_code.pp_val v ; assert false (* Invalid argument *) |
195 |
|
196 |
|
197 |
let pp_emf_cst_or_var_list = |
198 |
Utils.fprintf_list ~sep:",@ " pp_emf_cst_or_var |
199 |
|
200 |
|
201 |
(* Local Variables: *) |
202 |
(* compile-command: "make -C ../.." *) |
203 |
(* End: *) |