Skip to content

Commit 7fc0e55

Browse files
committed
Merge branch 'topic/kanig-272-fail2' into 'master'
Compute status for unproved VC in why3 Issue: eng/spark/spark2014#272 See merge request eng/spark/why3!104
2 parents eea70d1 + d1d3fb9 commit 7fc0e55

File tree

7 files changed

+159
-25
lines changed

7 files changed

+159
-25
lines changed

src/gnat/gnat_checks.ml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -896,6 +896,38 @@ module Save_VCs = struct
896896
Sysutil.write_file vc_fn "";
897897
vc_fn
898898

899+
let unproved_prover_answer session check =
900+
let check_rec = Gnat_expl.HCheck.find explmap check in
901+
let status = ref Gnat_expl.Unknown in
902+
let proof_attempt_status pa =
903+
match pa.Session_itp.proof_obsolete, pa.Session_itp.proof_state with
904+
| false, Some pr -> Gnat_expl.compress pr.Call_provers.pr_answer
905+
| _, _ -> Gnat_expl.Unknown
906+
in
907+
let rec transformation_status tfid =
908+
let subgoals = Session_itp.get_sub_tasks session tfid in
909+
List.fold_left (fun acc g -> Gnat_expl.merge_all_needed acc (goal_status g)) Gnat_expl.Unknown subgoals
910+
and transformation_list_status tl =
911+
List.fold_left (fun acc tfid ->
912+
Gnat_expl.merge_one_needed acc (transformation_status tfid))
913+
Gnat_expl.Unknown tl
914+
and proof_attempt_list_status proof_attempts =
915+
List.fold_left (fun acc pa ->
916+
Gnat_expl.merge_one_needed acc (proof_attempt_status pa))
917+
Gnat_expl.Unknown proof_attempts
918+
and goal_status g =
919+
let proof_attempts = Session_itp.get_proof_attempts session g in
920+
let transformations = Session_itp.get_transformations session g in
921+
let pa_status = proof_attempt_list_status proof_attempts in
922+
let tf_status = transformation_list_status transformations in
923+
Gnat_expl.merge_one_needed pa_status tf_status
924+
in
925+
GoalSet.iter (fun g ->
926+
let g_status = goal_status g in
927+
status := Gnat_expl.merge_all_needed !status g_status)
928+
check_rec.toplevel;
929+
!status
930+
899931
(* Group of functions to build a json object for a session tree.
900932
More precisely a session forest, because we start with a list of
901933
goals for a given check. See gnat_report.mli for the JSON

src/gnat/gnat_checks.mli

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,10 @@ module Save_VCs : sig
167167
(* get the file name for a given goal *)
168168

169169
val check_to_json : Session_itp.session -> Gnat_expl.check -> Json_base.json
170+
171+
val unproved_prover_answer :
172+
Session_itp.session -> Gnat_expl.check -> Gnat_expl.unproved_status
173+
(* get the unproved status for a given goal *)
170174
end
171175

172176
val all_split_leaf_goals : unit -> unit

src/gnat/gnat_expl.ml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,3 +648,44 @@ module HCheck = Hashtbl.Make (struct
648648

649649
let hash = check_hash
650650
end)
651+
652+
type unproved_status =
653+
| Unknown
654+
| Gave_up
655+
| Limit of { timeout : bool ; step : bool ; memory : bool }
656+
657+
let compress ans =
658+
match ans with
659+
| Call_provers.Valid
660+
| Call_provers.Invalid
661+
| Call_provers.Unknown _
662+
| Call_provers.Failure _
663+
| Call_provers.HighFailure _ -> Gave_up
664+
| Call_provers.Timeout ->
665+
Limit { timeout = true ; step = false ; memory = false }
666+
| Call_provers.OutOfMemory ->
667+
Limit { timeout = false ; step = false ; memory = true }
668+
| Call_provers.StepLimitExceeded ->
669+
Limit { timeout = false ; step = true ; memory = false }
670+
671+
let merge_all_needed s1 s2 =
672+
match s1, s2 with
673+
Unknown, _ -> s2
674+
| _, Unknown -> s1
675+
| Gave_up, _ -> Gave_up
676+
| _, Gave_up -> Gave_up
677+
| Limit l1, Limit l2 ->
678+
Limit { timeout = l1.timeout || l2.timeout ;
679+
step = l1.step || l2.step ;
680+
memory = l1.memory || l2.memory }
681+
682+
let merge_one_needed s1 s2 =
683+
match s1, s2 with
684+
Unknown, _ -> s2
685+
| _, Unknown -> s1
686+
| Gave_up, _ -> s2
687+
| _, Gave_up -> s1
688+
| Limit l1, Limit l2 ->
689+
Limit { timeout = l1.timeout || l2.timeout ;
690+
step = l1.step || l2.step ;
691+
memory = l1.memory || l2.memory }

src/gnat/gnat_expl.mli

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,3 +165,22 @@ val search_labels: Why3.Term.term -> vc_info option
165165

166166
val parse_line_spec : string -> limit_mode
167167
val parse_region_spec : string -> Gnat_loc.region
168+
169+
type unproved_status =
170+
| Unknown
171+
| Gave_up
172+
| Limit of { timeout : bool ; step : bool ; memory : bool }
173+
(* The unproved status of a goal contains information about the reason
174+
why the goal could not be proved. Note that "unknown" means the
175+
status is unknown, not that the prover answered unknown.*)
176+
177+
val compress : Call_provers.prover_answer -> unproved_status
178+
(* Convert a prover answer into an unproved status *)
179+
180+
val merge_all_needed : unproved_status -> unproved_status -> unproved_status
181+
(* Merge two statuses into one, assuming all proofs are needed
182+
for the check to prove. *)
183+
184+
val merge_one_needed : unproved_status -> unproved_status -> unproved_status
185+
(* Merge two statuses into one, assuming only one proof is needed
186+
for the check to prove. *)

src/gnat/gnat_main.ml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,8 @@ let report_messages c check =
258258
with Not_found -> default
259259
else { Gnat_expl.pretty_node = None; inlined = None }
260260
in
261-
Gnat_report.Not_Proved (extra_info, models, manual_info) in
261+
let answer_status = C.Save_VCs.unproved_prover_answer s check in
262+
Gnat_report.Not_Proved (extra_info, models, manual_info, answer_status) in
262263
Gnat_report.register check (C.Save_VCs.check_to_json s check) result
263264

264265
(* Escaping all debug printings *)

src/gnat/gnat_report.ml

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,18 @@ type result_info =
1515
| Not_Proved of
1616
Gnat_expl.extra_info *
1717
(Model_parser.model * Check_ce.rac_result option) list *
18-
(string * string) option
18+
(string * string) option *
19+
Gnat_expl.unproved_status
1920

2021
type msg =
21-
{ result : bool;
22-
stats : stats option;
23-
stats_checker : int;
24-
check_tree : Json_base.json;
25-
extra_info : Gnat_expl.extra_info;
26-
cntexmp_models : (Model_parser.model * Check_ce.rac_result option) list;
27-
manual_proof : (string * string) option
22+
{ result : bool;
23+
stats : stats option;
24+
stats_checker : int;
25+
check_tree : Json_base.json;
26+
extra_info : Gnat_expl.extra_info;
27+
cntexmp_models : (Model_parser.model * Check_ce.rac_result option) list;
28+
manual_proof : (string * string) option;
29+
unproved_status : Gnat_expl.unproved_status
2830
}
2931

3032
let msg_set : msg Gnat_expl.HCheck.t = Gnat_expl.HCheck.create 17
@@ -55,16 +57,17 @@ let adapt_stats statsopt =
5557
Some newstats
5658

5759
let register check check_tree result =
58-
let valid, extra_info, stats, models, manual =
60+
let valid, extra_info, stats, models, manual, unproved_status =
5961
match result with
6062
| Proved (stats, stats_checker) ->
6163
true,
6264
{Gnat_expl.pretty_node = None; inlined = None},
6365
Some (stats, stats_checker),
6466
[],
65-
None
66-
| Not_Proved (extra_info, models, manual) ->
67-
false, extra_info, None, models, manual
67+
None,
68+
Gnat_expl.Unknown
69+
| Not_Proved (extra_info, models, manual, unproved_status) ->
70+
false, extra_info, None, models, manual, unproved_status
6871
in
6972
if (Gnat_expl.HCheck.mem msg_set check) then assert false
7073
else begin
@@ -77,11 +80,12 @@ let register check check_tree result =
7780
stats_checker = Option.value ~default:0 stats_checker;
7881
check_tree = check_tree;
7982
cntexmp_models = models;
80-
manual_proof = manual } in
83+
manual_proof = manual;
84+
unproved_status = unproved_status } in
8185
Gnat_expl.HCheck.add msg_set check msg
8286
end
8387

84-
let get_cntexmp_models =
88+
let get_cntexmp_models =
8589
List.map (function
8690
(m, r) ->
8791
let json_result_state (state, _log) =
@@ -161,14 +165,32 @@ let get_extra_info i =
161165
"inline", Int (opt_int inline)
162166
]
163167

168+
let get_unproved_status status =
169+
let status, time, steps, memory =
170+
match status with
171+
| Gnat_expl.Unknown ->
172+
"unknown", false, false, false
173+
| Gnat_expl.Gave_up ->
174+
"gave_up", false, false, false
175+
| Gnat_expl.Limit { timeout; step; memory } ->
176+
"limit", timeout, step, memory
177+
in
178+
Record [
179+
"status", String status;
180+
"time", Bool time;
181+
"steps", Bool steps;
182+
"memory", Bool memory
183+
]
184+
164185
let get_msg (check, m) =
165186
Record (
166187
List.concat [
167188
[ "id", Int check.Gnat_expl.id ;
168189
"check_kind", String (Gnat_expl.check_kind_to_ada check.Gnat_expl.check_kind) ;
169190
"result", Bool m.result ;
170191
"check_tree", m.check_tree ;
171-
"extra_info", get_extra_info m.extra_info
192+
"extra_info", get_extra_info m.extra_info ;
193+
"unproved_status", get_unproved_status m.unproved_status
172194
] ;
173195
get_stats (m.stats, m.stats_checker);
174196
["cntexmps", List (get_cntexmp_models m.cntexmp_models)];

src/gnat/gnat_report.mli

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,15 @@ open Why3
2727
The "warnings" field is optional. If present, it contains a list of warnings
2828
that occured during execution of gnatwhy3.
2929
30-
result = { "id" : int,
31-
"check_kind" : string,
32-
"result" : bool,
33-
"extra_info" : extra_info,
34-
"vc_file" : string,
35-
"editor_cmd" : string,
36-
"check_tree" : list goal,
37-
"cntexmp" : cntexmp_rec
30+
result = { "id" : int,
31+
"check_kind" : string,
32+
"result" : bool,
33+
"extra_info" : extra_info,
34+
"vc_file" : string,
35+
"editor_cmd" : string,
36+
"check_tree" : list goal,
37+
"cntexmp" : cntexmp_rec,
38+
"unproved_status" : unproved_status
3839
}
3940
4041
The field "id" contains the id of the VC. The field "check_kind" identifies the
@@ -105,6 +106,19 @@ open Why3
105106
steps : integer,
106107
result : string }
107108
109+
The "unproved_status" field contains a summary of the reasons why
110+
the goal could not be proved. It is a record with the following fields:
111+
unproved_status = { "status" : string,
112+
"time" : bool,
113+
"steps" : bool,
114+
"memory" : bool}
115+
The "status" field contains one of the following strings:
116+
- "gave_up" : the prover gave up
117+
- "limit" : the prover reached some resource limit
118+
- "unknown" : the prover status is unknown (e.g., no proof attempt
119+
was made, or the goal was proved)
120+
The "time", "steps" and "memory" fields are booleans indicating whether
121+
the corresponding resource limit was reached.
108122
*)
109123

110124
type prover_stat =
@@ -125,8 +139,9 @@ type result_info =
125139
(Model_parser.model * Check_ce.rac_result option) list *
126140
(* counterexample models and their
127141
giant-step RAC result *)
128-
(string * string) option (* for manual provers, pair of
142+
(string * string) option * (* for manual provers, pair of
129143
(vc_file, editor_cmd) *)
144+
Gnat_expl.unproved_status
130145

131146
val register : Gnat_expl.check -> Json_base.json -> result_info -> unit
132147
(* [register check check_tree info] registers a proof result,

0 commit comments

Comments
 (0)