1
|
(********************************************************************)
|
2
|
(* *)
|
3
|
(* The LustreC compiler toolset / The LustreC Development Team *)
|
4
|
(* Copyright 2012 - -- ONERA - CNRS - INPT *)
|
5
|
(* *)
|
6
|
(* LustreC is free software, distributed WITHOUT ANY WARRANTY *)
|
7
|
(* under the terms of the GNU Lesser General Public License *)
|
8
|
(* version 2.1. *)
|
9
|
(* *)
|
10
|
(********************************************************************)
|
11
|
|
12
|
open Utils
|
13
|
open LustreSpec
|
14
|
open Corelang
|
15
|
|
16
|
let mkbool loc b =
|
17
|
mkexpr loc (Expr_const (const_of_bool b))
|
18
|
|
19
|
let mkident loc id =
|
20
|
mkexpr loc (Expr_ident id)
|
21
|
|
22
|
let mkfby loc e1 e2 =
|
23
|
mkexpr loc (Expr_arrow (e1, mkexpr loc (Expr_pre e2)))
|
24
|
|
25
|
let init loc restart state =
|
26
|
mkexpr loc (Expr_tuple [mkident loc restart; mkident loc state])
|
27
|
|
28
|
let add_branch (loc, expr, restart, st) cont =
|
29
|
mkexpr loc (Expr_ite (expr, mkexpr loc (Expr_tuple [mkbool loc restart; mkident loc st]), cont))
|
30
|
|
31
|
let mkhandler loc st unless until locals (stmts, asserts, annots) =
|
32
|
{hand_state = st;
|
33
|
hand_unless = unless;
|
34
|
hand_until = until;
|
35
|
hand_locals = locals;
|
36
|
hand_stmts = stmts;
|
37
|
hand_asserts = asserts;
|
38
|
hand_annots = annots;
|
39
|
hand_loc = loc}
|
40
|
|
41
|
let mkautomata loc id handlers =
|
42
|
{aut_id = id;
|
43
|
aut_handlers = handlers;
|
44
|
aut_loc = loc}
|
45
|
|
46
|
let rec handler_read reads handler =
|
47
|
let locals = List.fold_left (fun locals v -> ISet.add v.var_id locals) ISet.empty handler.hand_locals in
|
48
|
let allvars =
|
49
|
List.fold_left (fun read stmt ->
|
50
|
match stmt with
|
51
|
| Eq eq -> get_expr_vars read eq.eq_rhs
|
52
|
| Aut aut -> List.fold_left handler_read read aut.aut_handlers ) reads handler.hand_stmts
|
53
|
in ISet.diff allvars locals
|
54
|
|
55
|
let rec handler_write writes handler =
|
56
|
let locals = List.fold_left (fun locals v -> ISet.add v.var_id locals) ISet.empty handler.hand_locals in
|
57
|
let allvars =
|
58
|
List.fold_left (fun write stmt ->
|
59
|
match stmt with
|
60
|
| Eq eq -> List.fold_left (fun write v -> ISet.add v write) write eq.eq_lhs
|
61
|
| Aut aut -> List.fold_left handler_write write aut.aut_handlers) writes handler.hand_stmts
|
62
|
in ISet.diff allvars locals
|
63
|
|
64
|
let node_of_handler node aut_id handler =
|
65
|
let inputs = handler_read ISet.empty handler in
|
66
|
let outputs = handler_write ISet.empty handler in
|
67
|
{
|
68
|
node_id = Format.sprintf "%s_%s_handler" aut_id handler.hand_state;
|
69
|
node_type = Types.new_var ();
|
70
|
node_clock = Clocks.new_var true;
|
71
|
node_inputs = List.map (fun v -> get_node_var v node) (ISet.elements inputs);
|
72
|
node_outputs = List.map (fun v -> get_node_var v node) (ISet.elements outputs);
|
73
|
node_locals = handler.hand_locals;
|
74
|
node_gencalls = [];
|
75
|
node_checks = [];
|
76
|
node_asserts = handler.hand_asserts;
|
77
|
node_stmts = handler.hand_stmts;
|
78
|
node_dec_stateless = false;
|
79
|
node_stateless = None;
|
80
|
node_spec = None;
|
81
|
node_annot = handler.hand_annots
|
82
|
}
|
83
|
|
84
|
let expr_of_exit loc restart state conds tag =
|
85
|
mkexpr loc (Expr_when (List.fold_right add_branch conds (init loc restart state), state, tag))
|
86
|
|
87
|
let expr_of_handler loc restart state node tag =
|
88
|
let arg = mkexpr loc (Expr_tuple (List.map (fun v -> mkident loc v.var_id) node.node_inputs)) in
|
89
|
mkexpr loc (Expr_when (mkexpr loc (Expr_appl (node.node_id, arg, Some (restart, tag_true))), state, tag))
|
90
|
|
91
|
let assign_aut_handlers loc actual_r actual_s hnodes =
|
92
|
let outputs = (snd (List.hd hnodes)).node_outputs in
|
93
|
let assign_handlers = List.map (fun (hs, n) -> (hs, expr_of_handler loc actual_r actual_s n hs)) hnodes in
|
94
|
let assign_expr = mkexpr loc (Expr_merge (actual_s, assign_handlers)) in
|
95
|
let assign_eq = mkeq loc (List.map (fun v -> v.var_id) outputs, assign_expr) in
|
96
|
assign_eq
|
97
|
|
98
|
let typedef_of_automata node aut =
|
99
|
let tname = Format.sprintf "%s_type" aut.aut_id in
|
100
|
{ tydef_id = tname;
|
101
|
tydef_desc = Tydec_enum (List.map (fun h -> h.hand_state) aut.aut_handlers)
|
102
|
}
|
103
|
(*
|
104
|
let expand_automata_stmt (top_decls, locals, eqs) stmt =
|
105
|
match stmt with
|
106
|
| Eq eq -> (top_decls, locals, eq::eqs)
|
107
|
| Aut aut ->
|
108
|
|
109
|
|
110
|
let expand_automata top_node aut =
|
111
|
let node = node_of_top top_node in
|
112
|
let owner = top_node.top_decl_owner in
|
113
|
let typedef = typedef_of_automata node aut in
|
114
|
let initial = (List.hd aut.aut_handlers).hand_state in
|
115
|
let incoming_r = mk_new_name (get_node_vars node) (aut.aut_id ^ "__restart_in") in
|
116
|
let incoming_s = mk_new_name (get_node_vars node) (aut.aut_id ^ "__state_in") in
|
117
|
let actual_r = mk_new_name (get_node_vars node) (aut.aut_id ^ "__restart_act") in
|
118
|
let actual_s = mk_new_name (get_node_vars node) (aut.aut_id ^ "__state_act") in
|
119
|
let unless_handlers = List.map (fun h -> (h.hand_state, expr_of_exit h.hand_loc incoming_r incoming_s h.hand_unless h.hand_state)) aut.aut_handlers in
|
120
|
let unless_expr = mkexpr aut.aut_loc (Expr_merge (incoming_s, unless_handlers)) in
|
121
|
let unless_eq = mkeq aut.aut_loc ([actual_r; actual_s], unless_expr) in
|
122
|
let until_handlers = List.map (fun h -> (h.hand_state, expr_of_exit h.hand_loc actual_r actual_s h.hand_until h.hand_state)) aut.aut_handlers in
|
123
|
let until_expr = mkexpr aut.aut_loc (Expr_merge (actual_s, until_handlers)) in
|
124
|
let fby_until_expr = mkfby aut.aut_loc (init aut.aut_loc tag_false initial) until_expr in
|
125
|
let until_eq = mkeq aut.aut_loc ([incoming_r; incoming_s], fby_until_expr) in
|
126
|
let hnodes = List.map (fun h -> (h.hand_state, node_of_handler node aut.aut_id h)) aut.aut_handlers in
|
127
|
let assign_eq = assign_aut_handlers aut.aut_loc actual_r actual_s hnodes in
|
128
|
let tydec_bool = { ty_dec_desc = Tydec_bool; ty_dec_loc = aut.aut_loc } in
|
129
|
let tydec_const id = { ty_dec_desc = Tydec_const id; ty_dec_loc = aut.aut_loc } in
|
130
|
let ckdec_any = { ck_dec_desc = Ckdec_any; ck_dec_loc = aut.aut_loc } in
|
131
|
let locals' = [mkvar_decl aut.aut_loc (incoming_r, tydec_bool, ckdec_any, false);
|
132
|
mkvar_decl aut.aut_loc (actual_r , tydec_bool, ckdec_any, false);
|
133
|
mkvar_decl aut.aut_loc (incoming_s, tydec_const typedef.tydef_id, ckdec_any, false);
|
134
|
mkvar_decl aut.aut_loc (actual_s , tydec_const typedef.tydef_id, ckdec_any, false)] in
|
135
|
let eqs' = [Eq unless_eq; Eq assign_eq; Eq until_eq] in
|
136
|
let node' = { node with node_locals = locals'@node.node_locals; node_stmts = eqs'@node.node_stmts } in
|
137
|
(mktop_decl aut.aut_loc owner false (TypeDef typedef)) ::
|
138
|
{ top_node with top_decl_desc = Node node' } ::
|
139
|
(List.map2 (fun h (hs, n) -> mktop_decl h.hand_loc owner false (Node n)) aut.aut_handlers hnodes)
|
140
|
*)
|
141
|
let rec node_extract_automata top_decl =
|
142
|
match top_decl.top_decl_desc with
|
143
|
| Node nd -> []
|
144
|
| _ -> [top_decl]
|
145
|
(*
|
146
|
let extract_automata top_decls =
|
147
|
List.fold_left (fun top_decls top_decl -> ) top_decls
|
148
|
*)
|
149
|
(* Local Variables: *)
|
150
|
(* compile-command:"make -C .." *)
|
151
|
(* End: *)
|