1
|
open Basetypes
|
2
|
open Cmdliner
|
3
|
open Datatype
|
4
|
open Json_parser
|
5
|
open Sys
|
6
|
|
7
|
module ParseExt =
|
8
|
struct
|
9
|
open Yojson.Basic
|
10
|
|
11
|
|
12
|
let remove_quotes s =
|
13
|
let len = String.length s in
|
14
|
if String.get s 0 = '"' && String.get s (len-1) = '"' then
|
15
|
String.sub s 1 (len-2)
|
16
|
else (
|
17
|
Format.eprintf "No quotes in string %s@.@?" s;
|
18
|
assert false
|
19
|
)
|
20
|
|
21
|
let get_vars json =
|
22
|
let get_vdecls key json =
|
23
|
let s = json |> Util.member key |> to_string in
|
24
|
try
|
25
|
let s'= remove_quotes s in
|
26
|
if s' = "" then [] else
|
27
|
let lexbuf = Lexing.from_string s' in
|
28
|
Parser_lustre.vdecl_list Lexer_lustre.token lexbuf
|
29
|
with _ -> (Format.eprintf "Issues parsing decls for %s: %s@.@?" key s; assert false)
|
30
|
|
31
|
in
|
32
|
let inputs = get_vdecls "inputs" json in
|
33
|
let outputs = get_vdecls "outputs" json in
|
34
|
let variables = get_vdecls "variables" json in
|
35
|
inputs, outputs, variables
|
36
|
|
37
|
(* Protecting the generation of condition/action in case of an empty string
|
38
|
instead of a subtree *)
|
39
|
let protect default parse_fun embed_fun json =
|
40
|
try
|
41
|
let vars = get_vars json in
|
42
|
let actions = json |> Util.member "actions" |> to_string in
|
43
|
if actions = "[]" || actions = "" then default (* should not happen *) else (
|
44
|
Format.eprintf "Parsing string: %s@." actions;
|
45
|
let lexbuf = Lexing.from_string (remove_quotes actions) in
|
46
|
try
|
47
|
let content = parse_fun Lexer_lustre.token lexbuf in
|
48
|
Parsing.clear_parser ();
|
49
|
embed_fun content vars
|
50
|
with Parsing.Parse_error ->
|
51
|
let loc = Location.dummy_loc in
|
52
|
raise (Parse.Error (loc, Parse.String_Syntax_error actions))
|
53
|
)
|
54
|
with Util.Type_error _ -> (
|
55
|
Format.eprintf
|
56
|
"Unable to explore json subtree: empty string %s@." (to_string json);
|
57
|
default
|
58
|
)
|
59
|
|
60
|
let parse_condition =
|
61
|
protect
|
62
|
Condition.tru
|
63
|
Parser_lustre.expr
|
64
|
(fun e (in_,out_,locals_) ->
|
65
|
(* let vars = Corelang.get_expr_vars e in *)
|
66
|
Condition.cquote {
|
67
|
expr = e;
|
68
|
cinputs = in_;
|
69
|
coutputs = out_;
|
70
|
cvariables = locals_;
|
71
|
|
72
|
})
|
73
|
|
74
|
let parse_action =
|
75
|
protect Action.nil Parser_lustre.stmt_list
|
76
|
(fun (stmts, asserts, annots) (in_, out_, locals_) ->
|
77
|
if asserts != [] || annots != [] then
|
78
|
assert false (* Stateflow equations should not use asserts nor define
|
79
|
annotations *)
|
80
|
else
|
81
|
Action.aquote ({
|
82
|
defs = stmts;
|
83
|
ainputs = in_;
|
84
|
aoutputs = out_;
|
85
|
avariables = locals_;
|
86
|
})
|
87
|
)
|
88
|
|
89
|
let parse_event json = Some Yojson.Basic.(json |> to_string)
|
90
|
end
|
91
|
|
92
|
module JParse = Parser (ParseExt)
|
93
|
|
94
|
(* setup for logging *)
|
95
|
let setup_log style_renderer level =
|
96
|
Fmt_tty.setup_std_outputs ?style_renderer ();
|
97
|
Logs.set_level level;
|
98
|
Logs.set_reporter (Logs_fmt.reporter ());
|
99
|
()
|
100
|
|
101
|
let modular = ref 0
|
102
|
|
103
|
(* function representing the program to execute *)
|
104
|
let json_parse _ file pp =
|
105
|
try
|
106
|
let prog = JParse.parse_prog (Yojson.Basic.from_file file) in
|
107
|
if pp then
|
108
|
SF.pp_prog Format.std_formatter prog;
|
109
|
|
110
|
let module Model =
|
111
|
struct
|
112
|
let model = prog
|
113
|
let name = "toto" (* TODO find a meaningful name *)
|
114
|
let traces = [] (* TODO: shall we remove the traces field? *)
|
115
|
end
|
116
|
in
|
117
|
let modularmode =
|
118
|
match !modular with
|
119
|
| 2 -> true, true, true
|
120
|
| 1 -> false, true, false
|
121
|
| _ (* 0 *) -> false, false ,false
|
122
|
in
|
123
|
let state_vars = Datatype.SF.states Model.model in
|
124
|
let global_vars = Datatype.SF.global_vars Model.model in
|
125
|
|
126
|
let module T = CPS_lustre_generator.LustrePrinter (struct
|
127
|
let state_vars = state_vars
|
128
|
let global_vars = global_vars
|
129
|
end) in
|
130
|
let module Sem = CPS.Semantics (T) (Model) in
|
131
|
let prog = Sem.code_gen modularmode in
|
132
|
let header = List.map Corelang.mktop [
|
133
|
(LustreSpec.Open (false,"lustrec_math"));
|
134
|
(LustreSpec.Open (false,"conv"));
|
135
|
(LustreSpec.Open (true,"locallib"));
|
136
|
]
|
137
|
in
|
138
|
let prog =header@prog in
|
139
|
Options.print_dec_types := true;
|
140
|
(* Format.printf "%a@." Printers.pp_prog prog; *)
|
141
|
|
142
|
let auto_file = "sf_gen_test_auto.lus" in (* Could be changed *)
|
143
|
let auto_out = open_out auto_file in
|
144
|
let auto_fmt = Format.formatter_of_out_channel auto_out in
|
145
|
Format.fprintf auto_fmt "%a@." Printers.pp_prog prog;
|
146
|
Format.eprintf "Print initial lustre model with automaton in sf_gen_test_auto.lus@.";
|
147
|
|
148
|
let prog, deps = Compiler_stages.stage1 prog "" "" in
|
149
|
|
150
|
(* Format.printf "%a@." Printers.pp_prog prog; *)
|
151
|
let noauto_file = "sf_gen_test_noauto.lus" in (* Could be changed *)
|
152
|
let noauto_out = open_out noauto_file in
|
153
|
let noauto_fmt = Format.formatter_of_out_channel noauto_out in
|
154
|
Format.fprintf noauto_fmt "%a@." Printers.pp_prog prog;
|
155
|
Format.eprintf "Print expanded lustre model in sf_gen_test_noauto.lus@.";
|
156
|
()
|
157
|
|
158
|
with Parse.Error (l, err) -> Format.eprintf "Parse error at loc %a : %a@.@?" Location.pp_loc l Parse.pp_error err
|
159
|
|
160
|
(* term representing argument for file *)
|
161
|
let file =
|
162
|
let doc = "The file to parse." in
|
163
|
let env = Arg.env_var "JSON_FILE" ~doc in
|
164
|
let doc = "The file to parse." in
|
165
|
Arg.(required & pos 0 (some string) None & info [] ~env ~docv:"FILE" ~doc)
|
166
|
|
167
|
(* term representing argument for flag for pretty printing the program *)
|
168
|
let pp =
|
169
|
let doc = "Pretty print the resulting program" in
|
170
|
Arg.(value & flag & info ["pp"; "pretty-print"] ~docv:"PP" ~doc)
|
171
|
|
172
|
(* term for argument for logging *)
|
173
|
let setup_log_arg =
|
174
|
let env = Arg.env_var "TOOL_VERBOSITY" in
|
175
|
Term.(const setup_log $ Fmt_cli.style_renderer () $ Logs_cli.level ~env ())
|
176
|
|
177
|
(* term representing the program to execute *)
|
178
|
let json_parse_t = Term.(const json_parse $ setup_log_arg $ file $ pp)
|
179
|
|
180
|
(* term info for manpages etc. *)
|
181
|
let info =
|
182
|
let doc = "parse a JSON file representing a Stateflow model" in
|
183
|
let man = [
|
184
|
`S Manpage.s_bugs;
|
185
|
`P "Report bug to Github issues tracking." ]
|
186
|
in
|
187
|
Term.info "parse_json_file" ~doc ~exits:Term.default_exits ~man
|
188
|
|
189
|
(* program *)
|
190
|
let _ =
|
191
|
Term.exit @@ Term.eval (json_parse_t, info)
|