Skip to content

Commit 4f4b233

Browse files
committed
Backtrack in the prover.
1 parent cc192ed commit 4f4b233

1 file changed

Lines changed: 46 additions & 43 deletions

File tree

src/checker/Pulse.Checker.Prover.fst

Lines changed: 46 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -884,24 +884,24 @@ let prove_atom_unamb (g: env) (ctxt: list slprop_view) (goal: slprop_view) :
884884
with_uf_transaction fun _ ->
885885
teq_slprop g teq_cfg_unamb goal ctxt
886886
| _ -> false in
887-
debug_prover g (fun _ -> Printf.sprintf "prove_atom_unamb: searching for match for goal %s in ctxt %s\n" (show goal) (show ctxt));
887+
// debug_prover g (fun _ -> Printf.sprintf "prove_atom_unamb: searching for match for goal %s in ctxt %s\n" (show goal) (show ctxt));
888888
let ictxt = List.Tot.mapi (fun i ctxt -> i, ctxt) ctxt in
889889
let cands = T.filter (fun (i, ctxt) -> matches_mkeys ctxt) ictxt in
890-
debug_prover g (fun _ -> Printf.sprintf "prove_atom_unamb: found candidates %s\n" (show cands));
890+
// debug_prover g (fun _ -> Printf.sprintf "prove_atom_unamb: found candidates %s\n" (show cands));
891891
if Nil? cands then (
892-
debug_prover g (fun _ -> Printf.sprintf "prove_atom_unamb: no matches for %s in context %s\n" (show goal) (show ctxt));
892+
// debug_prover g (fun _ -> Printf.sprintf "prove_atom_unamb: no matches for %s in context %s\n" (show goal) (show ctxt));
893893
None
894894
)
895895
else if not (is_unamb g cands)
896896
then (
897-
debug_prover g (fun _ -> Printf.sprintf "prove_atom_unamb: no unambiguous matches for %s in context %s\n" (show goal) (show ctxt));
897+
// debug_prover g (fun _ -> Printf.sprintf "prove_atom_unamb: no unambiguous matches for %s in context %s\n" (show goal) (show ctxt));
898898
None
899899
)
900900
else
901901
let (i, cand) :: _ = cands in
902-
debug_prover g (fun _ -> Printf.sprintf "prove_atom_unamb: commiting to unify %s and %s\n" (show (elab_slprop cand)) (show goal));
902+
// debug_prover g (fun _ -> Printf.sprintf "prove_atom_unamb: commiting to unify %s and %s\n" (show (elab_slprop cand)) (show goal));
903903
let ok = teq_slprop g teq_cfg_full goal (elab_slprop cand) in
904-
debug_prover g (fun _ -> Printf.sprintf "prove_atom_unamb: result of unify %s and %s is %s\n" (show (elab_slprop cand)) (show goal) (show ok));
904+
debug_prover g (fun _ -> Printf.sprintf "prove_atom_unamb: unified %s and %s, result is %s\n" (show (elab_slprop cand)) (show goal) (show ok));
905905
let rest_ctxt = List.Tot.filter (fun (j, _) -> j <> i) ictxt |> List.Tot.map snd in
906906
Some (| g, rest_ctxt, [], [cand], fun g' ->
907907
let _ = check_slprop_equiv_ext (RU.range_of_term goal) g (elab_slprop cand) goal in
@@ -926,7 +926,7 @@ let prove_atom (g: env) (ctxt: list slprop_view) (allow_amb: bool) (goal: slprop
926926
if Nil? cands then None else
927927
if (if allow_amb then false else not (is_unamb g cands)) then None else
928928
let (i, cand)::_ = cands in
929-
debug_prover g (fun _ -> Printf.sprintf "prove_atom: committed to unifying %s and %s\n" (show (elab_slprop cand)) (show goal));
929+
// debug_prover g (fun _ -> Printf.sprintf "prove_atom: committed to unifying %s and %s\n" (show (elab_slprop cand)) (show goal));
930930
let ok = teq_slprop g teq_cfg_full goal (elab_slprop cand) in
931931
debug_prover g (fun _ -> Printf.sprintf "prove_atom: unified %s and %s, result is %s\n" (show (elab_slprop cand)) (show goal) (show ok));
932932
let rest_ctxt = List.Tot.filter (fun (j, _) -> j <> i) ictxt |> List.Tot.map snd in
@@ -950,6 +950,8 @@ noeq type penv = {
950950
penv_steps: nat;
951951
}
952952

953+
let penv_depth pg = List.length pg.penv_stack
954+
953955
let prover_lemmas_enabled () : T.Tac bool =
954956
match T.ext_getv "pulse:prover_lemmas" with
955957
| "" | "true" -> true
@@ -995,9 +997,9 @@ let try_apply_elim_lemma (g: env) (lid: R.name) (i: nat) (ctxt: slprop_view) :
995997
assume res == tm_unit;
996998
(match inspect_slprop g pre, i with
997999
| [pre'], 0 -> // only support elimination rules with single pre
998-
debug_prover g (fun _ -> Printf.sprintf "try_apply_eager_elim_lemma: ATTEMPTING %s by unifying %s and %s\n" (show lid) (show (elab_slprop ctxt)) (show pre));
1000+
// debug_prover g (fun _ -> Printf.sprintf "try_apply_eager_elim_lemma: ATTEMPTING %s by unifying %s and %s\n" (show lid) (show (elab_slprop ctxt)) (show pre));
9991001
if do_match pre' ctxt then (
1000-
debug_prover g (fun _ -> Printf.sprintf "try_apply_elim_lemma: applying %s by unifying %s and %s\n" (show lid) (show (elab_slprop ctxt)) (show pre));
1002+
// debug_prover g (fun _ -> Printf.sprintf "try_apply_elim_lemma: applying %s by unifying %s and %s\n" (show lid) (show (elab_slprop ctxt)) (show pre));
10011003
let ok = teq_slprop g teq_cfg_full pre (elab_slprop ctxt) in
10021004
debug_prover g (fun _ -> Printf.sprintf "try_apply_elim_lemma: unified %s and %s, result is %s\n" (show (elab_slprop ctxt)) (show pre) (show ok));
10031005
let post' = open_term' post unit_const 0 in
@@ -1024,7 +1026,7 @@ let try_apply_eager_intro_lemma (g: env) (lid: R.name) (i: nat) ctxt (goal: slpr
10241026
let do_match a b =
10251027
match a, b with
10261028
| Atom a_hd a_mkeys a, Atom b_hd b_mkeys b ->
1027-
debug_prover g (fun _ -> Printf.sprintf "do_match:\n%s and\n%s\n" (show a_mkeys) (show b_mkeys));
1029+
// debug_prover g (fun _ -> Printf.sprintf "do_match:\n%s and\n%s\n" (show a_mkeys) (show b_mkeys));
10281030
with_uf_transaction fun _ ->
10291031
teq_slprop g teq_cfg_first_mkeys_pass a b
10301032
| _ -> false in
@@ -1037,9 +1039,9 @@ let try_apply_eager_intro_lemma (g: env) (lid: R.name) (i: nat) ctxt (goal: slpr
10371039
let post' = open_term' post unit_const 0 in
10381040
(match inspect_slprop g post', i with
10391041
| [post''], 0 -> // only support introduction rules with single post
1040-
debug_prover g (fun _ -> Printf.sprintf "try_apply_eager_intro_lemma: ATTEMPTING %s by unifying %s and %s\n" (show lid) (show post) (show (elab_slprop goal)));
1042+
// debug_prover g (fun _ -> Printf.sprintf "try_apply_eager_intro_lemma: ATTEMPTING %s by unifying %s and %s\n" (show lid) (show post) (show (elab_slprop goal)));
10411043
if do_match post'' goal then (
1042-
debug_prover g (fun _ -> Printf.sprintf "try_apply_eager_intro_lemma: applying %s by unifying %s and %s\n" (show lid) (show post) (show (elab_slprop goal)));
1044+
// debug_prover g (fun _ -> Printf.sprintf "try_apply_eager_intro_lemma: applying %s by unifying %s and %s\n" (show lid) (show post) (show (elab_slprop goal)));
10431045
let ok = teq_slprop g teq_cfg_full post' (elab_slprop goal) in
10441046
debug_prover g (fun _ -> Printf.sprintf "try_apply_eager_intro_lemma: unified %s and %s, result is %s\n" (show post) (show (elab_slprop goal)) (show ok));
10451047
Some (| g, ctxt, [Unknown pre], [], fun g'' ->
@@ -1132,19 +1134,19 @@ let try_apply_intro_lemma (g: env) (lid: R.name) (i: nat) ctxt (goal: slprop_vie
11321134
assume res == tm_unit;
11331135
let post' = open_term' post unit_const 0 in
11341136
let post'' = inspect_slprop g post' in
1135-
debug_prover g (fun _ -> Printf.sprintf "try_apply_intro_lemma: %s %s %s\n" (show lid) (string_of_int i) (show post''));
1137+
// debug_prover g (fun _ -> Printf.sprintf "try_apply_intro_lemma: %s %s %s\n" (show lid) (string_of_int i) (show post''));
11361138
if i >= List.length post'' then None else
11371139
let post''_before, post''_i, post''_after = List.split3 post'' i in
11381140
let post''_rest = post''_before @ post''_after in
11391141
if do_match post''_i goal then (
1140-
debug_prover g (fun _ -> Printf.sprintf "try_apply_intro_lemma: applying %s by unifying %s and %s\n" (show lid) (show (elab_slprop post''_i)) (show (elab_slprop goal)));
1142+
// debug_prover g (fun _ -> Printf.sprintf "try_apply_intro_lemma: applying %s by unifying %s and %s\n" (show lid) (show (elab_slprop post''_i)) (show (elab_slprop goal)));
11411143
// Do not unify non-mkeys until after we run the prover on the subproblem.
11421144
let ok = teq_slprop g teq_cfg_first_mkeys_pass (elab_slprop post''_i) (elab_slprop goal) in
1143-
debug_prover g (fun _ -> Printf.sprintf "try_apply_intro_lemma: unified(1) %s and %s, result is %s\n" (show (elab_slprop post''_i)) (show (elab_slprop goal)) (show ok));
1145+
debug_prover g (fun _ -> Printf.sprintf "try_apply_intro_lemma: unified %s and %s, result is %s\n" (show (elab_slprop post''_i)) (show (elab_slprop goal)) (show ok));
11441146
Some (| g, [Unknown pre], fun subresult ->
11451147
let (| g', ctxt', k |) = prover_result_solved_unpack subresult in
11461148
let ok = teq_slprop g teq_cfg_full (elab_slprop post''_i) (elab_slprop goal) in
1147-
debug_prover g (fun _ -> Printf.sprintf "try_apply_intro_lemma: unified(2) %s and %s, result is %s\n" (show (elab_slprop post''_i)) (show (elab_slprop goal)) (show ok));
1149+
// debug_prover g (fun _ -> Printf.sprintf "try_apply_intro_lemma: unified(2) %s and %s, result is %s\n" (show (elab_slprop post''_i)) (show (elab_slprop goal)) (show ok));
11481150
(| g', ctxt' @ post''_rest, [], [goal], fun (g'': env { env_extends g'' g' }) ->
11491151
let c = C_STGhost inames { pre; post; res; u } in
11501152
let typing = core_check_term g' t T.E_Ghost ty in
@@ -1170,46 +1172,47 @@ let try_apply_intro_lemma (g: env) (lid: R.name) (i: nat) ctxt (goal: slprop_vie
11701172
None
11711173
#pop-options
11721174

1173-
let intro_lemma_main (g:penv) (ctxt: list slprop_view) (goal: slprop_view) :
1174-
T.Tac (option (
1175-
pg': penv &
1176-
subgoals: list slprop_view &
1177-
(res:prover_result_solved pg'.penv_env ctxt subgoals ->
1178-
T.Tac (prover_result g.penv_env ctxt [goal]))
1179-
)) =
1175+
let try_pick_and_rollback_uf_if_none #a #b (f: a -> T.Tac (option b)) (xs: list a) : T.Tac (option b) =
1176+
T.tryPick (fun x ->
1177+
T.try_with (fun _ ->
1178+
match f x with
1179+
| None -> T.raise (AbortUFTransaction true)
1180+
| y -> y)
1181+
(function
1182+
| AbortUFTransaction _ -> None
1183+
| ex -> T.raise ex)
1184+
) xs
1185+
1186+
let intro_lemma_step
1187+
(subprover : (pg: penv -> ctxt: list slprop_view -> goals: list slprop_view ->
1188+
T.Tac (prover_result pg.penv_env ctxt goals)))
1189+
(g:penv) (ctxt: list slprop_view) (goal: slprop_view) :
1190+
T.Tac (option (prover_result g.penv_env ctxt [goal])) =
11801191
match goal with
11811192
| Atom (FVarHead fv) mkeys p ->
11821193
let hd = FVarHead fv in
11831194
let breadcrumb = (fv, (match mkeys with Some mkeys -> mkeys | _ -> [p])) in
1184-
T.tryPick (fun plem ->
1195+
try_pick_and_rollback_uf_if_none (fun plem ->
11851196
if plem.plem_kind <> Intro then None else
11861197
if plem.plem_prop_head <> hd then None else
11871198
if already_in_stack g breadcrumb then None else
1188-
(debug_prover g.penv_env (fun _ -> Printf.sprintf "intro_lemma_main: trying to apply %s to %s\n" (show plem.plem_lid) (show p));
1199+
(debug_prover g.penv_env (fun _ -> Printf.sprintf "intro_lemma[%s]: trying to apply %s to %s\n" (string_of_int (penv_depth g)) (show plem.plem_lid) (show p));
11891200
match try_apply_intro_lemma g.penv_env plem.plem_lid plem.plem_prop_idx ctxt goal with
11901201
| Some (| g', subgoals, k |) ->
1191-
let g' = { g with penv_env = g'; penv_stack = breadcrumb :: g.penv_stack } in
1192-
Some ((| g', subgoals, k |)
1193-
<: (pg': penv &
1194-
subgoals: list slprop_view &
1195-
(res:prover_result_solved pg'.penv_env ctxt subgoals ->
1196-
T.Tac (prover_result g.penv_env ctxt [goal]))))
1202+
let pg' = { g with penv_env = g'; penv_stack = breadcrumb :: g.penv_stack } in
1203+
debug_prover g.penv_env (fun _ -> Printf.sprintf "intro_lemma[%s]: proving generated subproblem\n" (string_of_int (penv_depth g)));
1204+
let subresult = subprover pg' ctxt subgoals in
1205+
if not (prover_result_is_solved subresult) then (
1206+
debug_prover g.penv_env (fun _ -> Printf.sprintf "intro_lemma[%s]: subproblem failed for %s\n" (string_of_int (penv_depth g)) (show plem.plem_lid));
1207+
None
1208+
) else (
1209+
debug_prover g.penv_env (fun _ -> Printf.sprintf "intro_lemma[%s]: subproblem succeeded for %s\n" (string_of_int (penv_depth g)) (show plem.plem_lid));
1210+
Some (k subresult)
1211+
)
11971212
| None -> None)
11981213
) g.penv_plems
11991214
| _ -> None
12001215

1201-
let intro_lemma_step
1202-
(subprover : (pg: penv -> ctxt: list slprop_view -> goals: list slprop_view ->
1203-
T.Tac (prover_result pg.penv_env ctxt goals)))
1204-
(g:penv) (ctxt: list slprop_view) (goal: slprop_view) :
1205-
T.Tac (option (prover_result g.penv_env ctxt [goal])) =
1206-
if not g.penv_plems_enabled then None else
1207-
match intro_lemma_main g ctxt goal with
1208-
| None -> None
1209-
| Some (| pg', subgoals, k |) ->
1210-
let subresult = subprover pg' ctxt subgoals in
1211-
if not (prover_result_is_solved subresult) then None else
1212-
Some (k subresult)
12131216

12141217
let rec first_some #a (ks: list (unit -> T.Tac (option a))) : T.Tac (option a) =
12151218
match ks with

0 commit comments

Comments
 (0)