Revision 43aa67ec
Added by Teme Kahsai over 8 years ago
src/horn_backend.ml | ||
---|---|---|
18 | 18 |
| Types.Tstatic _ |
19 | 19 |
| Types.Tconst _ |
20 | 20 |
| Types.Tarrow _ |
21 |
| _ -> Format.eprintf "internal error: pp_type %a@."
|
|
21 |
| _ -> Format.eprintf "internal error: pp_type %a@." |
|
22 | 22 |
Types.print_ty t; assert false |
23 | 23 |
|
24 |
let pp_decl_var fmt id =
|
|
24 |
let pp_decl_var fmt id = |
|
25 | 25 |
Format.fprintf fmt "(declare-var %s %a)" |
26 | 26 |
id.var_id |
27 | 27 |
pp_type id.var_type |
... | ... | |
29 | 29 |
let pp_var fmt id = Format.pp_print_string fmt id.var_id |
30 | 30 |
|
31 | 31 |
|
32 |
let pp_conj pp fmt l =
|
|
33 |
match l with
|
|
32 |
let pp_conj pp fmt l = |
|
33 |
match l with |
|
34 | 34 |
[] -> assert false |
35 | 35 |
| [x] -> pp fmt x |
36 | 36 |
| _ -> fprintf fmt "(and @[<v 0>%a@]@ )" (Utils.fprintf_list ~sep:" " pp) l |
37 |
|
|
38 | 37 |
|
39 | 38 |
|
40 |
let concat prefix x = if prefix = "" then x else prefix ^ "." ^ x |
|
39 |
|
|
40 |
let concat prefix x = if prefix = "" then x else prefix ^ "." ^ x |
|
41 | 41 |
let rename f = (fun v -> {v with var_id = f v.var_id } ) |
42 | 42 |
let rename_machine p = rename (fun n -> concat p n) |
43 | 43 |
let rename_machine_list p = List.map (rename_machine p) |
44 |
|
|
44 |
|
|
45 | 45 |
let rename_current = rename (fun n -> n ^ "_c") |
46 | 46 |
let rename_current_list = List.map rename_current |
47 | 47 |
let rename_next = rename (fun n -> n ^ "_x") |
48 | 48 |
let rename_next_list = List.map rename_next |
49 | 49 |
|
50 | 50 |
|
51 |
let get_machine machines node_name =
|
|
52 |
List.find (fun m -> m.mname.node_id = node_name) machines
|
|
51 |
let get_machine machines node_name = |
|
52 |
List.find (fun m -> m.mname.node_id = node_name) machines |
|
53 | 53 |
|
54 | 54 |
let full_memory_vars machines machine = |
55 | 55 |
let rec aux fst prefix m = |
56 | 56 |
(rename_machine_list (if fst then prefix else concat prefix m.mname.node_id) m.mmemory) @ |
57 |
List.fold_left (fun accu (id, (n, _)) ->
|
|
58 |
let name = node_name n in
|
|
57 |
List.fold_left (fun accu (id, (n, _)) -> |
|
58 |
let name = node_name n in |
|
59 | 59 |
if name = "_arrow" then accu else |
60 | 60 |
let machine_n = get_machine machines name in |
61 | 61 |
( aux false (concat prefix (if fst then id else concat m.mname.node_id id)) machine_n ) @ accu |
62 |
) [] (m.minstances)
|
|
62 |
) [] (m.minstances) |
|
63 | 63 |
in |
64 | 64 |
aux true machine.mname.node_id machine |
65 | 65 |
|
66 |
let stateless_vars machines m =
|
|
66 |
let stateless_vars machines m = |
|
67 | 67 |
(rename_machine_list m.mname.node_id m.mstep.step_inputs)@ |
68 | 68 |
(rename_machine_list m.mname.node_id m.mstep.step_outputs) |
69 |
|
|
70 |
let step_vars machines m =
|
|
69 |
|
|
70 |
let step_vars machines m = |
|
71 | 71 |
(stateless_vars machines m)@ |
72 |
(rename_current_list (full_memory_vars machines m)) @
|
|
73 |
(rename_next_list (full_memory_vars machines m))
|
|
74 |
|
|
75 |
let init_vars machines m =
|
|
76 |
(stateless_vars machines m) @ (rename_next_list (full_memory_vars machines m))
|
|
77 |
|
|
72 |
(rename_current_list (full_memory_vars machines m)) @ |
|
73 |
(rename_next_list (full_memory_vars machines m)) |
|
74 |
|
|
75 |
let init_vars machines m = |
|
76 |
(stateless_vars machines m) @ (rename_next_list (full_memory_vars machines m)) |
|
77 |
|
|
78 | 78 |
(********************************************************************************************) |
79 | 79 |
(* Instruction Printing functions *) |
80 | 80 |
(********************************************************************************************) |
... | ... | |
107 | 107 |
let rec pp_horn_val ?(is_lhs=false) self pp_var fmt v = |
108 | 108 |
match v with |
109 | 109 |
| Cst c -> pp_horn_const fmt c |
110 |
| Array _
|
|
110 |
| Array _ |
|
111 | 111 |
| Access _ -> assert false (* no arrays *) |
112 | 112 |
| Power (v, n) -> assert false |
113 | 113 |
| LocalVar v -> pp_var fmt (rename_machine self v) |
114 | 114 |
| StateVar v -> |
115 | 115 |
if Types.is_array_type v.var_type |
116 |
then assert false
|
|
116 |
then assert false |
|
117 | 117 |
else pp_var fmt (rename_machine self ((if is_lhs then rename_next else rename_current) (* self *) v)) |
118 | 118 |
| Fun (n, vl) -> Format.fprintf fmt "%a" (Basic_library.pp_horn n (pp_horn_val self pp_var)) vl |
119 | 119 |
|
... | ... | |
133 | 133 |
*) |
134 | 134 |
let pp_assign m self pp_var fmt var_type var_name value = |
135 | 135 |
fprintf fmt "(= %a %a)" (pp_horn_val ~is_lhs:true self pp_var) var_name (pp_value_suffix self pp_var) value |
136 |
|
|
137 |
let pp_instance_call
|
|
136 |
|
|
137 |
let pp_instance_call |
|
138 | 138 |
machines ?(init=false) m self fmt i (inputs: value_t list) (outputs: var_decl list) = |
139 |
try (* stateful node instance *)
|
|
139 |
try (* stateful node instance *) |
|
140 | 140 |
begin |
141 | 141 |
let (n,_) = List.assoc i m.minstances in |
142 | 142 |
match node_name n, inputs, outputs with |
... | ... | |
145 | 145 |
pp_assign |
146 | 146 |
m |
147 | 147 |
self |
148 |
(pp_horn_var m)
|
|
148 |
(pp_horn_var m) |
|
149 | 149 |
fmt |
150 | 150 |
o.var_type (LocalVar o) i1 |
151 | 151 |
else |
152 | 152 |
pp_assign |
153 | 153 |
m self (pp_horn_var m) fmt |
154 | 154 |
o.var_type (LocalVar o) i2 |
155 |
|
|
155 |
|
|
156 | 156 |
end |
157 |
| name, _, _ ->
|
|
157 |
| name, _, _ -> |
|
158 | 158 |
begin |
159 | 159 |
let target_machine = List.find (fun m -> m.mname.node_id = name) machines in |
160 | 160 |
if init then |
161 | 161 |
Format.fprintf fmt "(%a %a%t%a%t%a)" |
162 |
pp_machine_init_name (node_name n)
|
|
162 |
pp_machine_init_name (node_name n) |
|
163 | 163 |
(* inputs *) |
164 |
(Utils.fprintf_list ~sep:" " (pp_horn_val self (pp_horn_var m)))
|
|
164 |
(Utils.fprintf_list ~sep:" " (pp_horn_val self (pp_horn_var m))) |
|
165 | 165 |
inputs |
166 |
(Utils.pp_final_char_if_non_empty " " inputs)
|
|
166 |
(Utils.pp_final_char_if_non_empty " " inputs) |
|
167 | 167 |
(* outputs *) |
168 |
(Utils.fprintf_list ~sep:" " (pp_horn_val self (pp_horn_var m)))
|
|
168 |
(Utils.fprintf_list ~sep:" " (pp_horn_val self (pp_horn_var m))) |
|
169 | 169 |
(List.map (fun v -> LocalVar v) outputs) |
170 | 170 |
(Utils.pp_final_char_if_non_empty " " outputs) |
171 | 171 |
(* memories (next) *) |
172 | 172 |
(Utils.fprintf_list ~sep:" " pp_var) ( |
173 |
rename_machine_list
|
|
174 |
(concat m.mname.node_id i)
|
|
173 |
rename_machine_list |
|
174 |
(concat m.mname.node_id i) |
|
175 | 175 |
(rename_next_list (full_memory_vars machines target_machine) |
176 |
)
|
|
176 |
) |
|
177 | 177 |
) |
178 | 178 |
else |
179 | 179 |
Format.fprintf fmt "(%a %a%t%a%t%a)" |
180 |
pp_machine_step_name (node_name n)
|
|
180 |
pp_machine_step_name (node_name n) |
|
181 | 181 |
(Utils.fprintf_list ~sep:" " (pp_horn_val self (pp_horn_var m))) inputs |
182 |
(Utils.pp_final_char_if_non_empty " " inputs)
|
|
183 |
(Utils.fprintf_list ~sep:" " (pp_horn_val self (pp_horn_var m)))
|
|
182 |
(Utils.pp_final_char_if_non_empty " " inputs) |
|
183 |
(Utils.fprintf_list ~sep:" " (pp_horn_val self (pp_horn_var m))) |
|
184 | 184 |
(List.map (fun v -> LocalVar v) outputs) |
185 | 185 |
(Utils.pp_final_char_if_non_empty " " outputs) |
186 | 186 |
(Utils.fprintf_list ~sep:" " pp_var) ( |
187 |
(rename_machine_list
|
|
188 |
(concat m.mname.node_id i)
|
|
187 |
(rename_machine_list |
|
188 |
(concat m.mname.node_id i) |
|
189 | 189 |
(rename_current_list (full_memory_vars machines target_machine)) |
190 |
) @
|
|
191 |
(rename_machine_list
|
|
192 |
(concat m.mname.node_id i)
|
|
190 |
) @ |
|
191 |
(rename_machine_list |
|
192 |
(concat m.mname.node_id i) |
|
193 | 193 |
(rename_next_list (full_memory_vars machines target_machine)) |
194 |
)
|
|
194 |
) |
|
195 | 195 |
) |
196 |
|
|
196 |
|
|
197 | 197 |
end |
198 | 198 |
end |
199 | 199 |
with Not_found -> ( (* stateless node instance *) |
200 | 200 |
let (n,_) = List.assoc i m.mcalls in |
201 | 201 |
Format.fprintf fmt "(%s %a%t%a)" |
202 | 202 |
(node_name n) |
203 |
(Utils.fprintf_list ~sep:" " (pp_horn_val self (pp_horn_var m)))
|
|
203 |
(Utils.fprintf_list ~sep:" " (pp_horn_val self (pp_horn_var m))) |
|
204 | 204 |
inputs |
205 |
(Utils.pp_final_char_if_non_empty " " inputs)
|
|
206 |
(Utils.fprintf_list ~sep:" " (pp_horn_val self (pp_horn_var m)))
|
|
205 |
(Utils.pp_final_char_if_non_empty " " inputs) |
|
206 |
(Utils.fprintf_list ~sep:" " (pp_horn_val self (pp_horn_var m))) |
|
207 | 207 |
(List.map (fun v -> LocalVar v) outputs) |
208 | 208 |
) |
209 | 209 |
|
... | ... | |
225 | 225 |
(Utils.fprintf_list ~sep:"@," (pp_machine_instr machines ~init:init m self)) el |
226 | 226 |
|
227 | 227 |
and pp_machine_instr machines ?(init=false) (m: machine_t) self fmt instr = |
228 |
match instr with
|
|
228 |
match instr with |
|
229 | 229 |
| MReset i -> |
230 | 230 |
pp_machine_init m self fmt i |
231 | 231 |
| MLocalAssign (i,v) -> |
... | ... | |
236 | 236 |
pp_assign |
237 | 237 |
m self (pp_horn_var m) fmt |
238 | 238 |
i.var_type (StateVar i) v |
239 |
| MStep ([i0], i, vl) when Basic_library.is_internal_fun i ->
|
|
239 |
| MStep ([i0], i, vl) when Basic_library.is_internal_fun i -> |
|
240 | 240 |
assert false (* This should not happen anymore *) |
241 | 241 |
| MStep (il, i, vl) -> |
242 | 242 |
pp_instance_call machines ~init:init m self fmt i vl il |
... | ... | |
251 | 251 |
|
252 | 252 |
|
253 | 253 |
(**************************************************************) |
254 |
|
|
255 |
let is_stateless m = m.minstances = [] && m.mmemory = [] |
|
256 | 254 |
|
257 |
(* Print the machine m: |
|
255 |
let is_stateless m = m.minstances = [] && m.mmemory = [] |
|
256 |
|
|
257 |
(* Print the machine m: |
|
258 | 258 |
two functions: m_init and m_step |
259 | 259 |
- m_init is a predicate over m memories |
260 | 260 |
- m_step is a predicate over old_memories, inputs, new_memories, outputs |
261 | 261 |
We first declare all variables then the two /rules/. |
262 | 262 |
*) |
263 |
let print_machine machines fmt m =
|
|
263 |
let print_machine machines fmt m = |
|
264 | 264 |
let pp_instr init = pp_machine_instr machines ~init:init m in |
265 |
if m.mname.node_id = arrow_id then
|
|
265 |
if m.mname.node_id = arrow_id then |
|
266 | 266 |
(* We don't print arrow function *) |
267 | 267 |
() |
268 |
else
|
|
269 |
begin
|
|
268 |
else |
|
269 |
begin |
|
270 | 270 |
Format.fprintf fmt "; %s@." m.mname.node_id; |
271 | 271 |
|
272 | 272 |
(* Printing variables *) |
273 |
Utils.fprintf_list ~sep:"@." pp_decl_var fmt
|
|
273 |
Utils.fprintf_list ~sep:"@." pp_decl_var fmt |
|
274 | 274 |
((step_vars machines m)@ |
275 | 275 |
(rename_machine_list m.mname.node_id m.mstep.step_locals)); |
276 | 276 |
Format.pp_print_newline fmt (); |
277 | 277 |
|
278 |
|
|
279 |
|
|
278 |
|
|
279 |
|
|
280 | 280 |
if is_stateless m then |
281 | 281 |
begin |
282 | 282 |
(* Declaring single predicate *) |
283 | 283 |
Format.fprintf fmt "(declare-rel %a (%a))@." |
284 | 284 |
pp_machine_stateless_name m.mname.node_id |
285 |
(Utils.fprintf_list ~sep:" " pp_type)
|
|
285 |
(Utils.fprintf_list ~sep:" " pp_type) |
|
286 | 286 |
(List.map (fun v -> v.var_type) (stateless_vars machines m)); |
287 |
|
|
287 |
|
|
288 | 288 |
(* Rule for single predicate *) |
289 | 289 |
Format.fprintf fmt "@[<v 2>(rule (=> @ %a@ (%a %a)@]@.))@.@." |
290 |
(pp_conj (pp_instr
|
|
291 |
true (* In this case, the boolean init can be set to true or false.
|
|
290 |
(pp_conj (pp_instr |
|
291 |
true (* In this case, the boolean init can be set to true or false. |
|
292 | 292 |
The node is stateless. *) |
293 | 293 |
m.mname.node_id) |
294 | 294 |
) |
... | ... | |
296 | 296 |
pp_machine_stateless_name m.mname.node_id |
297 | 297 |
(Utils.fprintf_list ~sep:" " pp_var) (stateless_vars machines m); |
298 | 298 |
end |
299 |
else
|
|
299 |
else |
|
300 | 300 |
begin |
301 | 301 |
(* Declaring predicate *) |
302 | 302 |
Format.fprintf fmt "(declare-rel %a (%a))@." |
303 | 303 |
pp_machine_init_name m.mname.node_id |
304 |
(Utils.fprintf_list ~sep:" " pp_type)
|
|
304 |
(Utils.fprintf_list ~sep:" " pp_type) |
|
305 | 305 |
(List.map (fun v -> v.var_type) (init_vars machines m)); |
306 |
|
|
306 |
|
|
307 | 307 |
Format.fprintf fmt "(declare-rel %a (%a))@." |
308 | 308 |
pp_machine_step_name m.mname.node_id |
309 |
(Utils.fprintf_list ~sep:" " pp_type)
|
|
309 |
(Utils.fprintf_list ~sep:" " pp_type) |
|
310 | 310 |
(List.map (fun v -> v.var_type) (step_vars machines m)); |
311 |
|
|
311 |
|
|
312 | 312 |
Format.pp_print_newline fmt (); |
313 | 313 |
|
314 | 314 |
(* Rule for init *) |
... | ... | |
328 | 328 |
| [] -> () |
329 | 329 |
| assertsl -> begin |
330 | 330 |
let pp_val = pp_horn_val ~is_lhs:true m.mname.node_id pp_var in |
331 |
|
|
331 |
|
|
332 | 332 |
Format.fprintf fmt "; Asserts@."; |
333 | 333 |
Format.fprintf fmt "(assert @[<v 2>%a@]@ )@.@.@." |
334 | 334 |
(pp_conj pp_val) assertsl; |
335 |
|
|
336 |
(** TEME: the following code is the one we described. But it generates a segfault in z3
|
|
335 |
|
|
336 |
(** TEME: the following code is the one we described. But it generates a segfault in z3 |
|
337 | 337 |
Format.fprintf fmt "; Asserts for init@."; |
338 | 338 |
Format.fprintf fmt "@[<v 2>(assert (=> @ (and @[<v 0>%a@]@ (%a %a))@ %a@]@.))@.@.@." |
339 | 339 |
(Utils.fprintf_list ~sep:"@ " (pp_instr true m.mname.node_id)) m.mstep.step_instrs |
340 | 340 |
pp_machine_init_name m.mname.node_id |
341 | 341 |
(Utils.fprintf_list ~sep:" " pp_var) (init_vars machines m) |
342 |
(pp_conj pp_val) assertsl;
|
|
343 |
|
|
342 |
(pp_conj pp_val) assertsl; |
|
343 |
|
|
344 | 344 |
Format.fprintf fmt "; Asserts for step@."; |
345 | 345 |
Format.fprintf fmt "@[<v 2>(assert (=> @ (and @[<v 0>%a@]@ (%a %a))@ %a@]@.))@.@." |
346 | 346 |
(Utils.fprintf_list ~sep:"@ " (pp_instr false m.mname.node_id)) m.mstep.step_instrs |
... | ... | |
351 | 351 |
*) |
352 | 352 |
end |
353 | 353 |
); |
354 |
|
|
354 |
|
|
355 | 355 |
(* |
356 | 356 |
match m.mspec with |
357 | 357 |
None -> () (* No node spec; we do nothing *) |
358 |
| Some {requires = []; ensures = [EnsuresExpr e]; behaviors = []} ->
|
|
359 |
(
|
|
358 |
| Some {requires = []; ensures = [EnsuresExpr e]; behaviors = []} -> |
|
359 |
( |
|
360 | 360 |
(* For the moment, we only deal with simple case: single ensures, no other parameters *) |
361 | 361 |
() |
362 |
|
|
362 |
|
|
363 | 363 |
) |
364 | 364 |
| _ -> () (* Other cases give nothing *) |
365 |
*)
|
|
365 |
*) |
|
366 | 366 |
end |
367 | 367 |
end |
368 | 368 |
|
... | ... | |
374 | 374 |
let main_output = |
375 | 375 |
rename_machine_list machine.mname.node_id machine.mstep.step_outputs |
376 | 376 |
in |
377 |
let main_output_dummy =
|
|
377 |
let main_output_dummy = |
|
378 | 378 |
rename_machine_list ("dummy" ^ machine.mname.node_id) machine.mstep.step_outputs |
379 | 379 |
in |
380 |
let main_memory_next =
|
|
380 |
let main_memory_next = |
|
381 | 381 |
(rename_next_list (* machine.mname.node_id *) (full_memory_vars machines machine)) @ |
382 | 382 |
main_output |
383 | 383 |
in |
384 |
let main_memory_current =
|
|
384 |
let main_memory_current = |
|
385 | 385 |
(rename_current_list (* machine.mname.node_id *) (full_memory_vars machines machine)) @ |
386 | 386 |
main_output_dummy |
387 | 387 |
in |
388 | 388 |
|
389 | 389 |
(* Special case when the main node is stateless *) |
390 |
let init_name, step_name =
|
|
390 |
let init_name, step_name = |
|
391 | 391 |
if is_stateless machine then |
392 | 392 |
pp_machine_stateless_name, pp_machine_stateless_name |
393 | 393 |
else |
... | ... | |
395 | 395 |
in |
396 | 396 |
|
397 | 397 |
Format.fprintf fmt "(declare-rel MAIN (%a))@." |
398 |
(Utils.fprintf_list ~sep:" " pp_type)
|
|
398 |
(Utils.fprintf_list ~sep:" " pp_type) |
|
399 | 399 |
(List.map (fun v -> v.var_type) main_memory_next); |
400 |
|
|
400 |
|
|
401 | 401 |
Format.fprintf fmt "; Initial set@."; |
402 | 402 |
Format.fprintf fmt "(declare-rel INIT_STATE ())@."; |
403 | 403 |
Format.fprintf fmt "(rule INIT_STATE)@."; |
... | ... | |
408 | 408 |
|
409 | 409 |
Format.fprintf fmt "; Inductive def@."; |
410 | 410 |
(Utils.fprintf_list ~sep:" " (fun fmt v -> Format.fprintf fmt "%a@." pp_decl_var v)) fmt main_output_dummy; |
411 |
Format.fprintf fmt
|
|
411 |
Format.fprintf fmt |
|
412 | 412 |
"@[<v 2>(rule (=> @ (and @[<v 0>(MAIN %a)@ (@[<v 0>%a %a@])@]@ )@ (MAIN %a)@]@.))@.@." |
413 | 413 |
(Utils.fprintf_list ~sep:" " pp_var) main_memory_current |
414 | 414 |
step_name node |
415 | 415 |
(Utils.fprintf_list ~sep:" " pp_var) (step_vars machines machine) |
416 |
(Utils.fprintf_list ~sep:" " pp_var) main_memory_next
|
|
416 |
(Utils.fprintf_list ~sep:" " pp_var) main_memory_next |
|
417 | 417 |
|
418 | 418 |
let check_prop machines fmt node machine = |
419 | 419 |
let main_output = |
420 | 420 |
rename_machine_list machine.mname.node_id machine.mstep.step_outputs |
421 | 421 |
in |
422 |
let main_memory_next =
|
|
422 |
let main_memory_next = |
|
423 | 423 |
(rename_next_list (full_memory_vars machines machine)) @ main_output |
424 | 424 |
in |
425 | 425 |
Format.fprintf fmt "; Property def@."; |
... | ... | |
428 | 428 |
(pp_conj pp_var) main_output |
429 | 429 |
(Utils.fprintf_list ~sep:" " pp_var) main_memory_next |
430 | 430 |
; |
431 |
if !Options.horn_queries then |
|
432 |
Format.fprintf fmt "(query ERR)@." |
|
431 |
Format.fprintf fmt "(query ERR)@." |
|
433 | 432 |
|
434 | 433 |
|
435 | 434 |
let cex_computation machines fmt node machine = |
... | ... | |
438 | 437 |
let cex_input = |
439 | 438 |
rename_machine_list machine.mname.node_id machine.mstep.step_inputs |
440 | 439 |
in |
441 |
let cex_input_dummy =
|
|
440 |
let cex_input_dummy = |
|
442 | 441 |
rename_machine_list ("dummy" ^ machine.mname.node_id) machine.mstep.step_inputs |
443 | 442 |
in |
444 | 443 |
let cex_output = |
445 | 444 |
rename_machine_list machine.mname.node_id machine.mstep.step_outputs |
446 | 445 |
in |
447 |
let cex_output_dummy =
|
|
446 |
let cex_output_dummy = |
|
448 | 447 |
rename_machine_list ("dummy" ^ machine.mname.node_id) machine.mstep.step_outputs |
449 | 448 |
in |
450 |
let cex_memory_next =
|
|
449 |
let cex_memory_next = |
|
451 | 450 |
cex_input @ (rename_next_list (full_memory_vars machines machine)) @ cex_output |
452 | 451 |
in |
453 |
let cex_memory_current =
|
|
452 |
let cex_memory_current = |
|
454 | 453 |
cex_input_dummy @ (rename_current_list (full_memory_vars machines machine)) @ cex_output_dummy |
455 | 454 |
in |
456 | 455 |
|
457 | 456 |
(* Special case when the cex node is stateless *) |
458 |
let init_name, step_name =
|
|
457 |
let init_name, step_name = |
|
459 | 458 |
if is_stateless machine then |
460 | 459 |
pp_machine_stateless_name, pp_machine_stateless_name |
461 | 460 |
else |
... | ... | |
463 | 462 |
in |
464 | 463 |
|
465 | 464 |
Format.fprintf fmt "(declare-rel CEX (Int %a))@.@." |
466 |
(Utils.fprintf_list ~sep:" " pp_type)
|
|
465 |
(Utils.fprintf_list ~sep:" " pp_type) |
|
467 | 466 |
(List.map (fun v -> v.var_type) cex_memory_next); |
468 |
|
|
467 |
|
|
469 | 468 |
Format.fprintf fmt "; Initial set@."; |
470 | 469 |
Format.fprintf fmt "@[<v 2>(rule (=> @ (and @[<v 0>INIT_STATE@ (@[<v 0>%a %a@])@]@ )@ (CEX 0 %a)@]@.))@.@." |
471 | 470 |
init_name node |
... | ... | |
476 | 475 |
(* Declare dummy inputs. Outputs should have been declared previously with collecting sem *) |
477 | 476 |
(Utils.fprintf_list ~sep:" " (fun fmt v -> Format.fprintf fmt "%a@." pp_decl_var v)) fmt cex_input_dummy; |
478 | 477 |
Format.fprintf fmt "(declare-var cexcpt Int)@."; |
479 |
Format.fprintf fmt
|
|
478 |
Format.fprintf fmt |
|
480 | 479 |
"@[<v 2>(rule (=> @ (and @[<v 0>(CEX cexcpt %a)@ (@[<v 0>%a %a@])@]@ )@ (CEX (+ 1 cexcpt) %a)@]@.))@.@." |
481 | 480 |
(Utils.fprintf_list ~sep:" " pp_var) cex_memory_current |
482 | 481 |
step_name node |
483 | 482 |
(Utils.fprintf_list ~sep:" " pp_var) (step_vars machines machine) |
484 |
(Utils.fprintf_list ~sep:" " pp_var) cex_memory_next
|
|
483 |
(Utils.fprintf_list ~sep:" " pp_var) cex_memory_next |
|
485 | 484 |
|
486 | 485 |
let get_cex machines fmt node machine = |
487 | 486 |
let cex_input = |
... | ... | |
490 | 489 |
let cex_output = |
491 | 490 |
rename_machine_list machine.mname.node_id machine.mstep.step_outputs |
492 | 491 |
in |
493 |
let cex_memory_next =
|
|
492 |
let cex_memory_next = |
|
494 | 493 |
cex_input @ (rename_next_list (full_memory_vars machines machine)) @ cex_output |
495 | 494 |
in |
496 | 495 |
Format.fprintf fmt "; Property def@."; |
... | ... | |
499 | 498 |
(pp_conj pp_var) cex_output |
500 | 499 |
(Utils.fprintf_list ~sep:" " pp_var) cex_memory_next |
501 | 500 |
; |
502 |
if !Options.horn_queries then |
|
503 |
Format.fprintf fmt "(query CEXTRACE)@." |
|
501 |
Format.fprintf fmt "(query CEXTRACE)@." |
|
504 | 502 |
|
505 | 503 |
|
506 |
let main_print machines fmt =
|
|
507 |
if !Options.main_node <> "" then
|
|
504 |
let main_print machines fmt = |
|
505 |
if !Options.main_node <> "" then |
|
508 | 506 |
begin |
509 | 507 |
let node = !Options.main_node in |
510 | 508 |
let machine = get_machine machines node in |
... | ... | |
512 | 510 |
|
513 | 511 |
collecting_semantics machines fmt node machine; |
514 | 512 |
check_prop machines fmt node machine; |
515 |
|
|
516 |
cex_computation machines fmt node machine; |
|
517 |
get_cex machines fmt node machine
|
|
513 |
if !Options.horn_cex then( |
|
514 |
cex_computation machines fmt node machine;
|
|
515 |
get_cex machines fmt node machine)
|
|
518 | 516 |
end |
519 | 517 |
|
520 | 518 |
|
521 | 519 |
let translate fmt basename prog machines = |
522 | 520 |
List.iter (print_machine machines fmt) (List.rev machines); |
523 |
|
|
524 |
main_print machines fmt
|
|
521 |
|
|
522 |
main_print machines fmt |
|
525 | 523 |
|
526 | 524 |
|
527 | 525 |
let traces_file fmt basename prog machines = |
528 |
Format.fprintf fmt
|
|
526 |
Format.fprintf fmt |
|
529 | 527 |
"; Horn code traceability generated by %s@.; SVN version number %s@.@." |
530 |
(Filename.basename Sys.executable_name)
|
|
528 |
(Filename.basename Sys.executable_name) |
|
531 | 529 |
Version.number; |
532 | 530 |
|
533 | 531 |
(* We extract the annotation dealing with traceability *) |
534 |
let machines_traces = List.map (fun m ->
|
|
535 |
let traces : (ident * expr) list=
|
|
532 |
let machines_traces = List.map (fun m -> |
|
533 |
let traces : (ident * expr) list= |
|
536 | 534 |
let all_annots = List.flatten (List.map (fun ann -> ann.annots) m.mannot) in |
537 |
let filtered =
|
|
538 |
List.filter (fun (kwds, _) -> kwds = ["horn_backend";"trace"]) all_annots
|
|
535 |
let filtered = |
|
536 |
List.filter (fun (kwds, _) -> kwds = ["horn_backend";"trace"]) all_annots |
|
539 | 537 |
in |
540 | 538 |
let content = List.map snd filtered in |
541 | 539 |
(* Elements are supposed to be a pair (tuple): variable, expression *) |
542 |
List.map (fun ee ->
|
|
543 |
match ee.eexpr_quantifiers, ee.eexpr_qfexpr.expr_desc with
|
|
540 |
List.map (fun ee -> |
|
541 |
match ee.eexpr_quantifiers, ee.eexpr_qfexpr.expr_desc with |
|
544 | 542 |
| [], Expr_tuple [v;e] -> ( |
545 |
match v.expr_desc with
|
|
546 |
| Expr_ident vid -> vid, e
|
|
543 |
match v.expr_desc with |
|
544 |
| Expr_ident vid -> vid, e |
|
547 | 545 |
| _ -> assert false ) |
548 | 546 |
| _ -> assert false) |
549 | 547 |
content |
550 | 548 |
in |
551 |
|
|
549 |
|
|
552 | 550 |
m, traces |
553 | 551 |
|
554 | 552 |
) machines |
... | ... | |
558 | 556 |
let compute_mems m = |
559 | 557 |
let rec aux fst prefix m = |
560 | 558 |
(List.map (fun mem -> (prefix, mem)) m.mmemory) @ |
561 |
List.fold_left (fun accu (id, (n, _)) ->
|
|
562 |
let name = node_name n in
|
|
559 |
List.fold_left (fun accu (id, (n, _)) -> |
|
560 |
let name = node_name n in |
|
563 | 561 |
if name = "_arrow" then accu else |
564 | 562 |
let machine_n = get_machine machines name in |
565 |
( aux false ((id,machine_n)::prefix) machine_n )
|
|
563 |
( aux false ((id,machine_n)::prefix) machine_n ) |
|
566 | 564 |
@ accu |
567 |
) [] m.minstances
|
|
565 |
) [] m.minstances |
|
568 | 566 |
in |
569 | 567 |
aux true [] m |
570 | 568 |
in |
571 | 569 |
|
572 | 570 |
List.iter (fun m -> |
573 | 571 |
Format.fprintf fmt "; Node %s@." m.mname.node_id; |
574 |
|
|
575 |
let memories_old =
|
|
576 |
List.map (fun (p, v) ->
|
|
572 |
|
|
573 |
let memories_old = |
|
574 |
List.map (fun (p, v) -> |
|
577 | 575 |
let machine = match p with | [] -> m | (_,m')::_ -> m' in |
578 | 576 |
let traces = List.assoc machine machines_traces in |
579 | 577 |
if List.mem_assoc v.var_id traces then |
... | ... | |
582 | 580 |
else |
583 | 581 |
(* We keep the variable as is: we create an expression v *) |
584 | 582 |
p, mkexpr Location.dummy_loc (Expr_ident v.var_id) |
585 |
|
|
586 |
) (compute_mems m)
|
|
583 |
|
|
584 |
) (compute_mems m) |
|
587 | 585 |
in |
588 | 586 |
let memories_next = (* We remove the topest pre in each expression *) |
589 |
List.map
|
|
590 |
(fun (prefix, ee) ->
|
|
591 |
match ee.expr_desc with
|
|
592 |
| Expr_pre e -> prefix, e
|
|
593 |
| _ -> Format.eprintf
|
|
594 |
"Mem Failure: (prefix: %a, eexpr: %a)@.@?"
|
|
595 |
(Utils.fprintf_list ~sep:","
|
|
596 |
(fun fmt (id,n) -> fprintf fmt "(%s,%s)" id n.mname.node_id ))
|
|
597 |
(List.rev prefix)
|
|
598 |
Printers.pp_expr ee;
|
|
587 |
List.map |
|
588 |
(fun (prefix, ee) -> |
|
589 |
match ee.expr_desc with |
|
590 |
| Expr_pre e -> prefix, e |
|
591 |
| _ -> Format.eprintf |
|
592 |
"Mem Failure: (prefix: %a, eexpr: %a)@.@?" |
|
593 |
(Utils.fprintf_list ~sep:"," |
|
594 |
(fun fmt (id,n) -> fprintf fmt "(%s,%s)" id n.mname.node_id )) |
|
595 |
(List.rev prefix) |
|
596 |
Printers.pp_expr ee; |
|
599 | 597 |
assert false) |
600 | 598 |
memories_old |
601 | 599 |
in |
... | ... | |
631 | 629 |
(Utils.fprintf_list ~sep:" " pp_var) (m.mstep.step_inputs@m.mstep.step_outputs) |
632 | 630 |
(fun fmt -> match memories_old with [] -> () | _ -> fprintf fmt " ") |
633 | 631 |
(Utils.fprintf_list ~sep:" " (fun fmt (prefix,ee) -> fprintf fmt "%a(%a)" pp_prefix_rev prefix Printers.pp_expr ee)) (memories_old@memories_next); |
634 |
Format.pp_print_newline fmt ();
|
|
632 |
Format.pp_print_newline fmt (); |
|
635 | 633 |
) (List.rev machines); |
636 |
|
|
634 |
|
|
637 | 635 |
|
638 | 636 |
(* Local Variables: *) |
639 | 637 |
(* compile-command:"make -C .." *) |
Also available in: Unified diff
Fixed horn backend to make query for properties. More work needed for cex
git-svn-id: https://cavale.enseeiht.fr/svn/lustrec/lustre_compiler/trunk@311 041b043f-8d7c-46b2-b46e-ef0dd855326e