From be1e8f0175bff88b413a77a888a849c6e93b50e7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Loi=CC=88c=20Correnson?= <loic.correnson@cea.fr>
Date: Thu, 13 Apr 2023 19:08:26 +0200
Subject: [PATCH] [wp] proof strategy

---
 src/plugins/wp/ProofStrategy.ml  |  9 ++++
 src/plugins/wp/ProofStrategy.mli |  1 +
 src/plugins/wp/ProverScript.ml   | 84 +++++++++++++++++++++++++++++++-
 3 files changed, 92 insertions(+), 2 deletions(-)

diff --git a/src/plugins/wp/ProofStrategy.ml b/src/plugins/wp/ProofStrategy.ml
index 9112e292372..6498a2dae7c 100644
--- a/src/plugins/wp/ProofStrategy.ml
+++ b/src/plugins/wp/ProofStrategy.ml
@@ -301,6 +301,15 @@ let fallback = function
   | Strategy s -> resolve s
   | Tactic _ | Auto _ | Provers _ -> None
 
+let auto = function
+  | Strategy _  | Tactic _ | Provers _ -> None
+  | Auto s ->
+    match Strategy.lookup ~id:s.value with
+    | exception Not_found ->
+      Wp_parameters.error ~source:(fst s.loc) ~once:true
+        "Auto-Strategy '%s' not found (skipped)." s.value ; None
+    | h -> Some h
+
 (* -------------------------------------------------------------------------- *)
 (* --- Strategy Tactical Step                                             --- *)
 (* -------------------------------------------------------------------------- *)
diff --git a/src/plugins/wp/ProofStrategy.mli b/src/plugins/wp/ProofStrategy.mli
index ea8b19ec6ac..c9d50c46ee4 100644
--- a/src/plugins/wp/ProofStrategy.mli
+++ b/src/plugins/wp/ProofStrategy.mli
@@ -35,6 +35,7 @@ val hints : WpPropId.prop_id -> strategy list
 
 val alternatives : strategy -> alternative list
 val provers : alternative -> VCS.prover list * float
+val auto : alternative -> Strategy.heuristic option
 val fallback : alternative -> strategy option
 val tactic : tree -> node -> strategy -> alternative -> node list option
 
diff --git a/src/plugins/wp/ProverScript.ml b/src/plugins/wp/ProverScript.ml
index 623583773bc..a2696a88325 100644
--- a/src/plugins/wp/ProverScript.ml
+++ b/src/plugins/wp/ProverScript.ml
@@ -317,7 +317,87 @@ and autofork env ~depth fork =
 (* --- Proof Strategy Alternatives                                        --- *)
 (* -------------------------------------------------------------------------- *)
 
-(*TODO*)
+type solver = ProofEngine.node -> bool Task.task
+
+let success = Task.return true
+let failed = Task.return false
+let unknown : solver = fun _ -> failed
+
+let (+>>) (a : solver) (b : solver) : solver =
+  fun node -> a node >>= fun ok -> if ok then success else b node
+
+let rec sequence (f : 'a -> solver) = function
+  | [] -> unknown
+  | x::xs -> f x +>> sequence f xs
+
+let rec explore_strategie env p s : solver =
+  sequence
+    (explore_alternative env p s)
+    (ProofStrategy.alternatives s)
+
+and explore_alternative env p s a : solver =
+  explore_provers env a +>>
+  explore_tactic env p s a +>>
+  explore_auto env p a +>>
+  explore_fallback env p a
+
+and explore_provers env a : solver =
+  let provers,timeout = ProofStrategy.provers a in
+  sequence (explore_prover env timeout) provers
+
+and explore_prover env timeout prover node =
+  let wpo = ProofEngine.goal node in
+  let result = Wpo.get_result wpo prover in
+  if VCS.is_valid result then success else
+  if VCS.is_verdict result then failed else
+    let config = { VCS.default with timeout = Some timeout } in
+    Env.prove env wpo ~config prover
+
+and explore_tactic env process s a node =
+  match ProofStrategy.tactic env.tree node s a with
+  | None -> failed
+  | Some nodes -> List.iter process nodes ; success
+
+and explore_auto env process a node =
+  match ProofStrategy.auto a with
+  | None -> failed
+  | Some h ->
+    match ProverSearch.search env.tree ~anchor:node [h] with
+    | None -> failed
+    | Some fork ->
+      List.iter (fun (_,node) -> process node) @@
+      snd @@ ProofEngine.commit fork ; success
+
+and explore_fallback env process a node =
+  match ProofStrategy.fallback a with
+  | None -> failed
+  | Some s -> explore_strategie env process s node
+
+let explore_hint env process node =
+  match ProofEngine.get_hint node with
+  | None -> failed
+  | Some s ->
+    match ProofStrategy.find s with
+    | None -> failed
+    | Some s -> explore_strategie env process s node
+
+let explore_further env process strategy node =
+  let marked =
+    match ProofEngine.get_hint node with
+    | None -> false
+    | Some s -> ProofStrategy.name strategy = s
+  in if marked then failed else explore_strategie env process strategy node
+
+let explore_further_hints env process =
+  let wpo = ProofEngine.main env.Env.tree in
+  sequence (explore_further env process) (ProofStrategy.hints wpo.po_pid)
+
+(* -------------------------------------------------------------------------- *)
+(* --- Automated Solving                                                  --- *)
+(* -------------------------------------------------------------------------- *)
+
+let automated env process : solver =
+  auto env +>> explore_hint env process +>> explore_further_hints env process
 
 (* -------------------------------------------------------------------------- *)
 (* --- Apply Script Tactic                                                --- *)
@@ -342,7 +422,7 @@ let rec crawl env on_child node = function
 
   | [] ->
     let node = ProofEngine.anchor (Env.tree env) ?node () in
-    auto env node >>= fun ok ->
+    automated env on_child node >>= fun ok ->
     if ok then Env.validate env else Env.stuck env ;
     Task.return ()
 
-- 
GitLab