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 (vars_to_exprl ~prefix:"sout_" 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 = [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
|