lustrec / src / tools / stateflow / semantics / cPS_lustre_generator.ml @ 68601cf5
History | View | Annotate | Download (11.7 KB)
1 |
open Basetypes |
---|---|
2 |
open ActiveStates |
3 |
open CPS_transformer |
4 |
|
5 |
let ff = Format.fprintf |
6 |
|
7 |
module LustrePrinter ( |
8 |
Vars : sig |
9 |
val state_vars : ActiveStates.Vars.t |
10 |
val global_vars : LustreSpec.var_decl list |
11 |
end) : TransformerType = |
12 |
struct |
13 |
include TransformerStub |
14 |
|
15 |
type name_t = string |
16 |
type t_base = { statements : LustreSpec.statement list; assert_false: bool } |
17 |
type t = name_t -> name_t -> (ActiveStates.Vars.t * t_base) |
18 |
|
19 |
|
20 |
let new_loc, reset_loc = |
21 |
let cpt = ref 0 in |
22 |
((fun () -> incr cpt; Format.sprintf "loc_%i" !cpt), |
23 |
(fun () -> cpt := 0)) |
24 |
|
25 |
let new_aut, reset_aut = |
26 |
let cpt = ref 0 in |
27 |
((fun () -> incr cpt; Format.sprintf "aut_%i" !cpt), |
28 |
(fun () -> cpt := 0)) |
29 |
|
30 |
let pp_path prefix fmt path = |
31 |
Format.fprintf fmt "%s%t" |
32 |
prefix |
33 |
(fun fmt -> Utils.fprintf_list ~sep:"_" Format.pp_print_string fmt path) |
34 |
|
35 |
let pp_typed_path sin fmt path = |
36 |
Format.fprintf fmt "%a : bool" (pp_path sin) path |
37 |
|
38 |
let pp_vars sin fmt vars = |
39 |
Format.fprintf fmt "%t" (fun fmt -> Utils.fprintf_list ~sep:", " (pp_path sin) fmt (ActiveStates.Vars.elements vars)) |
40 |
let pp_vars_decl sin fmt vars = |
41 |
Format.fprintf fmt "%t" (fun fmt -> Utils.fprintf_list ~sep:"; " (pp_typed_path sin) fmt (ActiveStates.Vars.elements vars)) |
42 |
|
43 |
let var_to_ident prefix p = |
44 |
pp_path prefix Format.str_formatter p; |
45 |
Format.flush_str_formatter () |
46 |
|
47 |
let vars_to_ident_list ?(prefix="") vars = |
48 |
List.map ( |
49 |
fun p -> var_to_ident prefix p |
50 |
) (ActiveStates.Vars.elements vars) |
51 |
|
52 |
let mkvar name typ = |
53 |
let loc = Location.dummy_loc in |
54 |
Corelang.mkvar_decl |
55 |
loc |
56 |
(name, typ, Corelang.mkclock loc LustreSpec.Ckdec_any, false, None) |
57 |
|
58 |
let var_to_vdecl ?(prefix="") var typ = mkvar (var_to_ident prefix var) typ |
59 |
let state_vars_to_vdecl_list ?(prefix="") vars = |
60 |
let bool_type = Corelang.mktyp Location.dummy_loc LustreSpec.Tydec_bool in |
61 |
List.map |
62 |
(fun v -> var_to_vdecl ~prefix:prefix v bool_type) |
63 |
(ActiveStates.Vars.elements vars) |
64 |
|
65 |
let mk_locals locs = |
66 |
ActiveStates.Vars.fold (fun v accu -> |
67 |
(state_vars_to_vdecl_list ~prefix:(List.hd v) Vars.state_vars)@accu |
68 |
) locs [] |
69 |
(* TODO: declare global vars *) |
70 |
|
71 |
let mkeq = Corelang.mkeq Location.dummy_loc |
72 |
let mkexpr = Corelang.mkexpr Location.dummy_loc |
73 |
let mkpredef_call = Corelang.mkpredef_call Location.dummy_loc |
74 |
let expr_of_bool b = mkexpr (LustreSpec.Expr_const (Corelang.const_of_bool b)) |
75 |
let mkstmt_eq lhs_vars ?(prefix_lhs="") rhs = |
76 |
{ statements = [ |
77 |
LustreSpec.Eq ( |
78 |
mkeq ( |
79 |
vars_to_ident_list ~prefix:prefix_lhs lhs_vars, (* lhs *) |
80 |
rhs (* rhs *) |
81 |
) |
82 |
) |
83 |
]; |
84 |
assert_false = false |
85 |
} |
86 |
let base_to_assert b = |
87 |
if b.assert_false then |
88 |
[{LustreSpec.assert_expr = expr_of_bool false; assert_loc = Location.dummy_loc}] |
89 |
else |
90 |
[] |
91 |
|
92 |
|
93 |
let var_to_expr ?(prefix="") p = |
94 |
let id = var_to_ident prefix p in |
95 |
Corelang.expr_of_ident id Location.dummy_loc |
96 |
|
97 |
let vars_to_exprl ?(prefix="") vars = |
98 |
List.map |
99 |
(fun p -> var_to_expr ~prefix:prefix p) |
100 |
(ActiveStates.Vars.elements vars) |
101 |
|
102 |
|
103 |
(* Events *) |
104 |
let event_type_decl = |
105 |
Corelang.mktop |
106 |
( |
107 |
LustreSpec.TypeDef { |
108 |
LustreSpec.tydef_id = "event_type"; |
109 |
tydef_desc = LustreSpec.Tydec_int |
110 |
} |
111 |
) |
112 |
|
113 |
let event_type = { |
114 |
LustreSpec.ty_dec_desc = LustreSpec.Tydec_const "event_type"; |
115 |
LustreSpec.ty_dec_loc = Location.dummy_loc; |
116 |
} |
117 |
|
118 |
let event_var = mkvar "event" event_type |
119 |
|
120 |
|
121 |
let const_map : (event_base_t, int) Hashtbl.t = Hashtbl.create 13 |
122 |
let get_event_const e = |
123 |
try Hashtbl.find const_map e |
124 |
with Not_found -> ( |
125 |
let nb = Hashtbl.length const_map in |
126 |
Hashtbl.add const_map e nb; |
127 |
nb |
128 |
) |
129 |
|
130 |
|
131 |
|
132 |
let null sin sout = |
133 |
let expr_list = vars_to_exprl ~prefix:sin Vars.state_vars in |
134 |
ActiveStates.Vars.empty, |
135 |
( |
136 |
(* Nothing happen here: out_vars = in_vars *) |
137 |
let rhs = mkexpr (LustreSpec.Expr_tuple expr_list) in |
138 |
mkstmt_eq ~prefix_lhs:sout Vars.state_vars rhs |
139 |
) |
140 |
|
141 |
let bot sin sout = |
142 |
let (vars, tr) = null sin sout in |
143 |
( |
144 |
ActiveStates.Vars.empty, |
145 |
{ tr with assert_false = true } |
146 |
) |
147 |
|
148 |
let ( >> ) tr1 tr2 sin sout = |
149 |
let l = new_loc () in |
150 |
let (vars1, tr1) = tr1 sin l in |
151 |
let (vars2, tr2) = tr2 l sout in |
152 |
(ActiveStates.Vars.add [l] (ActiveStates.Vars.union vars1 vars2), |
153 |
{ |
154 |
statements = tr1.statements @ tr2.statements; |
155 |
assert_false = tr1.assert_false || tr2.assert_false |
156 |
} |
157 |
) |
158 |
|
159 |
let pp_name : |
160 |
type c. c call_t -> c -> unit = |
161 |
fun call -> |
162 |
match call with |
163 |
| Ecall -> (fun (p, p', f) -> |
164 |
Format.fprintf Format.str_formatter "theta%a%a%a_%a" |
165 |
pp_call call |
166 |
(pp_path "_from_") p |
167 |
(pp_path "_to_") p' |
168 |
pp_frontier f) |
169 |
| Dcall -> (fun p -> |
170 |
Format.fprintf Format.str_formatter "theta%a%a" |
171 |
pp_call call |
172 |
(pp_path "_from_") p) |
173 |
| Xcall -> (fun (p, f) -> |
174 |
Format.fprintf Format.str_formatter "theta%a%a_%a" |
175 |
pp_call call |
176 |
(pp_path "_from_") p |
177 |
pp_frontier f) |
178 |
|
179 |
|
180 |
let mkcall' : |
181 |
type c. name_t -> name_t -> c call_t -> c -> t_base = |
182 |
fun sin sout call arg -> |
183 |
pp_name call arg; |
184 |
let funname = Format.flush_str_formatter () in |
185 |
let args = (Corelang.expr_of_vdecl event_var)::(vars_to_exprl ~prefix:sin Vars.state_vars) in |
186 |
let rhs = mkpredef_call funname args in |
187 |
mkstmt_eq ~prefix_lhs:sout Vars.state_vars rhs |
188 |
|
189 |
let mkact' action sin sout = |
190 |
match action with |
191 |
| Action.Call (c, a) -> mkcall' sin sout c a |
192 |
| Action.Quote a -> |
193 |
let funname = "action_" ^ a.ident in |
194 |
let args = vars_to_exprl ~prefix:sin Vars.state_vars in |
195 |
let rhs = mkpredef_call funname args in |
196 |
mkstmt_eq ~prefix_lhs:sout Vars.state_vars rhs |
197 |
| Action.Open p -> |
198 |
let vars' = ActiveStates.Vars.remove p Vars.state_vars in |
199 |
(* eq1: sout_p = true *) |
200 |
let eq1 = mkeq ([var_to_ident sout p] , expr_of_bool true) in |
201 |
(* eq2: sout_xx = sin_xx *) |
202 |
let expr_list = vars_to_exprl ~prefix:sin vars' in |
203 |
let rhs = mkexpr (LustreSpec.Expr_tuple expr_list) in |
204 |
let eq2 = mkeq (vars_to_ident_list ~prefix:sout vars', rhs) in |
205 |
{ |
206 |
statements = [ |
207 |
LustreSpec.Eq (eq1); |
208 |
LustreSpec.Eq (eq2); |
209 |
]; |
210 |
assert_false = false |
211 |
} |
212 |
|
213 |
| Action.Close p -> |
214 |
let vars' = ActiveStates.Vars.remove p Vars.state_vars in |
215 |
(* eq1: sout_p = false *) |
216 |
let eq1 = mkeq ([var_to_ident sout p] , expr_of_bool false) in |
217 |
(* eq2: sout_xx = sin_xx *) |
218 |
let expr_list = vars_to_exprl ~prefix:sin vars' in |
219 |
let rhs = mkexpr (LustreSpec.Expr_tuple expr_list) in |
220 |
let eq2 = mkeq (vars_to_ident_list ~prefix:sout vars', rhs) in |
221 |
{ |
222 |
statements = [ |
223 |
LustreSpec.Eq (eq1); |
224 |
LustreSpec.Eq (eq2); |
225 |
]; |
226 |
assert_false = false |
227 |
} |
228 |
|
229 |
| Action.Nil -> |
230 |
let expr_list = vars_to_exprl ~prefix:sin Vars.state_vars in |
231 |
let rhs = mkexpr (LustreSpec.Expr_tuple expr_list) in |
232 |
mkstmt_eq ~prefix_lhs:sout Vars.state_vars rhs |
233 |
|
234 |
let eval_act kenv (action : act_t) = |
235 |
(*Format.printf "----- action = %a@." Action.pp_act action;*) |
236 |
(fun sin sout -> (ActiveStates.Vars.empty, |
237 |
mkact' action sin sout )) |
238 |
|
239 |
let rec mkcond' sin condition = |
240 |
(*Format.printf "----- cond = %a@." Condition.pp_cond condition;*) |
241 |
match condition with |
242 |
| Condition.True -> expr_of_bool true |
243 |
| Condition.Active p -> var_to_expr ~prefix:sin p |
244 |
| Condition.Event e -> |
245 |
mkpredef_call "=" [ |
246 |
Corelang.expr_of_vdecl event_var; |
247 |
mkexpr (LustreSpec.Expr_const (LustreSpec.Const_int (get_event_const e))) |
248 |
] |
249 |
| Condition.Neg cond -> mkpredef_call "not" [mkcond' sin cond] |
250 |
| Condition.And (cond1, cond2) -> mkpredef_call "&&" [mkcond' sin cond1; |
251 |
mkcond' sin cond2] |
252 |
| Condition.Quote c -> c (* TODO: shall we prefix with sin ? *) |
253 |
|
254 |
let rec eval_cond condition (ok:t) ko sin sout = |
255 |
let open LustreSpec in |
256 |
let loc = Location.dummy_loc in |
257 |
(*Format.printf "----- cond = %a@." Condition.pp_cond condition;*) |
258 |
let (vars1, tr1) = ok sin sout in |
259 |
let (vars2, tr2) = ko sin sout in |
260 |
let (vars0, tr0) = bot sin sout in |
261 |
let aut = new_aut () in |
262 |
(ActiveStates.Vars.empty, |
263 |
{ |
264 |
statements = [ |
265 |
Aut ( |
266 |
{ aut_id = aut; |
267 |
aut_loc = loc; |
268 |
aut_handlers = |
269 |
[ |
270 |
(* Default mode : CenterPoint *) |
271 |
{ hand_state = "CenterPoint_" ^ aut; |
272 |
hand_unless = [ |
273 |
(loc, mkcond' sin condition, true (* restart *), "Cond_" ^ aut); |
274 |
(loc, mkcond' sin (Condition.Neg condition), true (* restart *), "NotCond_" ^ aut); |
275 |
]; |
276 |
hand_until = []; |
277 |
hand_locals = []; |
278 |
hand_stmts = tr0.statements; |
279 |
hand_asserts = base_to_assert tr0; |
280 |
hand_annots = []; |
281 |
hand_loc = loc; |
282 |
}; |
283 |
(* Cond mode *) |
284 |
{ hand_state = "Cond_" ^ aut; |
285 |
hand_unless = []; |
286 |
hand_until = [ |
287 |
(loc, expr_of_bool true, true (* restart *), "CenterPoint_" ^ aut); |
288 |
]; |
289 |
hand_locals = mk_locals vars1; |
290 |
hand_stmts = tr1.statements; |
291 |
hand_asserts = base_to_assert tr1; |
292 |
hand_annots = []; |
293 |
hand_loc = loc; |
294 |
}; |
295 |
(* NotCond mode *) |
296 |
{ hand_state = "NotCond_" ^ aut; |
297 |
hand_unless = []; |
298 |
hand_until = [ |
299 |
(loc, expr_of_bool true, true (* restart *), "CenterPoint_" ^ aut); |
300 |
]; |
301 |
hand_locals = mk_locals vars2; |
302 |
hand_stmts = tr2.statements; |
303 |
hand_asserts = base_to_assert tr2; |
304 |
hand_annots = []; |
305 |
hand_loc = loc; |
306 |
}; |
307 |
] |
308 |
} |
309 |
) |
310 |
]; |
311 |
assert_false = false |
312 |
} |
313 |
) |
314 |
|
315 |
let mktransformer tr = |
316 |
let (vars, tr) = tr "sin_" "sout_" |
317 |
in tr |
318 |
|
319 |
let mkcomponent : |
320 |
type c. c call_t -> c -> t -> LustreSpec.program = |
321 |
fun call args -> |
322 |
fun tr -> |
323 |
reset_loc (); |
324 |
let (vars', tr') = tr "sin_" "sout_" in |
325 |
pp_name call args; |
326 |
let funname = Format.flush_str_formatter () in |
327 |
let node = |
328 |
Corelang.mktop ( |
329 |
LustreSpec.Node {LustreSpec.node_id = funname; |
330 |
node_type = Types.new_var (); |
331 |
node_clock = Clocks.new_var true; |
332 |
node_inputs = event_var :: state_vars_to_vdecl_list ~prefix:"sin_" Vars.state_vars; |
333 |
node_outputs = state_vars_to_vdecl_list ~prefix:"sout_" Vars.state_vars; |
334 |
node_locals = mk_locals vars'; (* TODO: add global vars *) |
335 |
node_gencalls = []; |
336 |
node_checks = []; |
337 |
node_stmts = tr'.statements; |
338 |
node_asserts = base_to_assert tr'; |
339 |
node_dec_stateless = false; |
340 |
node_stateless = None; |
341 |
node_spec = None; |
342 |
node_annot = []} |
343 |
) |
344 |
in |
345 |
[node] |
346 |
|
347 |
let mk_main_loop () = |
348 |
(* let loc = Location.dummy_loc in *) |
349 |
|
350 |
let call_stmt = |
351 |
(* (%t) -> pre (thetaCallD_from_principal (event, %a)) *) |
352 |
let init = mkexpr |
353 |
(LustreSpec.Expr_tuple (List.map (fun _ -> expr_of_bool false) (ActiveStates.Vars.elements Vars.state_vars))) |
354 |
in |
355 |
let args = (Corelang.expr_of_vdecl event_var):: |
356 |
(vars_to_exprl ~prefix:"sout_" Vars.state_vars) |
357 |
in |
358 |
let call_expr = mkpredef_call "thetaCallD_from_principal" args in |
359 |
let pre_call_expr = mkexpr (LustreSpec.Expr_pre (call_expr)) in |
360 |
let rhs = mkexpr (LustreSpec.Expr_arrow (init, pre_call_expr)) in |
361 |
mkstmt_eq Vars.state_vars ~prefix_lhs:"sout_" rhs |
362 |
in |
363 |
let node_principal = |
364 |
Corelang.mktop ( |
365 |
LustreSpec.Node {LustreSpec.node_id = "principal_loop"; |
366 |
node_type = Types.new_var (); |
367 |
node_clock = Clocks.new_var true; |
368 |
node_inputs = List.map Corelang.copy_var_decl [event_var]; |
369 |
node_outputs = state_vars_to_vdecl_list ~prefix:"sout_" Vars.state_vars; |
370 |
node_locals = []; (* TODO: add global vars *) |
371 |
node_gencalls = []; |
372 |
node_checks = []; |
373 |
node_asserts = base_to_assert call_stmt; |
374 |
node_stmts = call_stmt.statements; |
375 |
node_dec_stateless = false; |
376 |
node_stateless = None; |
377 |
node_spec = None; |
378 |
node_annot = []} |
379 |
) |
380 |
in |
381 |
node_principal |
382 |
|
383 |
|
384 |
let mkprincipal tr = |
385 |
event_type_decl :: mkcomponent Dcall ["principal"] tr @ [mk_main_loop ()] |
386 |
|
387 |
end |