aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tactics/class_tactics.ml213
1 files changed, 129 insertions, 84 deletions
diff --git a/tactics/class_tactics.ml b/tactics/class_tactics.ml
index e645182b8a..76316f6191 100644
--- a/tactics/class_tactics.ml
+++ b/tactics/class_tactics.ml
@@ -37,13 +37,17 @@ open Hints
(** Hint database named "typeclass_instances", now created directly in Auto *)
-let typeclasses_debug = ref false
+let typeclasses_debug = ref 0
let typeclasses_depth = ref None
let typeclasses_modulo_eta = ref false
let set_typeclasses_modulo_eta d = (:=) typeclasses_modulo_eta d
let get_typeclasses_modulo_eta () = !typeclasses_modulo_eta
+let typeclasses_limit_intros = ref false
+let set_typeclasses_limit_intros d = (:=) typeclasses_limit_intros d
+let get_typeclasses_limit_intros () = !typeclasses_limit_intros
+
let typeclasses_dependency_order = ref false
let set_typeclasses_dependency_order d = (:=) typeclasses_dependency_order d
let get_typeclasses_dependency_order () = !typeclasses_dependency_order
@@ -58,7 +62,11 @@ let get_compat_version d =
| _ -> Flags.Current
let typeclasses_unif_compat = ref Flags.V8_5
-let set_typeclasses_unif_compat d = (:=) typeclasses_unif_compat d
+let set_typeclasses_unif_compat d =
+ if d == Flags.Current then set_typeclasses_limit_intros false
+ else set_typeclasses_limit_intros true;
+ (:=) typeclasses_unif_compat d
+
let get_typeclasses_unif_compat () = !typeclasses_unif_compat
let set_typeclasses_unif_compat_string d =
set_typeclasses_unif_compat (get_compat_version d)
@@ -73,9 +81,21 @@ let set_typeclasses_compat_string d =
let get_typeclasses_compat_string () =
Flags.pr_version (get_typeclasses_compat ())
-
-open Goptions
+let set_typeclasses_debug d = (:=) typeclasses_debug (if d then 1 else 0)
+let get_typeclasses_debug () = if !typeclasses_debug > 0 then true else false
+
+let set_typeclasses_verbose =
+ function None -> typeclasses_debug := 0
+ | Some n -> (:=) typeclasses_debug n
+let get_typeclasses_verbose () =
+ if !typeclasses_debug = 0 then None else Some !typeclasses_debug
+
+let set_typeclasses_depth d = (:=) typeclasses_depth d
+let get_typeclasses_depth () = !typeclasses_depth
+
+open Goptions
+
let _ =
declare_bool_option
{ optsync = true;
@@ -89,6 +109,16 @@ let _ =
declare_bool_option
{ optsync = true;
optdepr = false;
+ optname = "do typeclass search avoiding eta-expansions " ^
+ " in proof terms (expensive)";
+ optkey = ["Typeclasses";"Limit";"Intros"];
+ optread = get_typeclasses_limit_intros;
+ optwrite = set_typeclasses_limit_intros; }
+
+let _ =
+ declare_bool_option
+ { optsync = true;
+ optdepr = false;
optname = "during typeclass resolution, solve instances according to their dependency order";
optkey = ["Typeclasses";"Dependency";"Order"];
optread = get_typeclasses_dependency_order;
@@ -120,6 +150,44 @@ let _ =
optkey = ["Typeclasses";"Unification";"Compatibility"];
optread = get_typeclasses_unif_compat_string;
optwrite = set_typeclasses_unif_compat_string; }
+
+let set_typeclasses_debug =
+ declare_bool_option
+ { optsync = true;
+ optdepr = false;
+ optname = "debug output for typeclasses proof search";
+ optkey = ["Typeclasses";"Debug"];
+ optread = get_typeclasses_debug;
+ optwrite = set_typeclasses_debug; }
+
+let _ =
+ declare_bool_option
+ { optsync = true;
+ optdepr = false;
+ optname = "debug output for typeclasses proof search";
+ optkey = ["Debug";"Typeclasses"];
+ optread = get_typeclasses_debug;
+ optwrite = set_typeclasses_debug; }
+
+let _ =
+ declare_int_option
+ { optsync = true;
+ optdepr = false;
+ optname = "verbosity of debug output for typeclasses proof search";
+ optkey = ["Typeclasses";"Debug";"Verbosity"];
+ optread = get_typeclasses_verbose;
+ optwrite = set_typeclasses_verbose; }
+
+let set_typeclasses_depth =
+ declare_int_option
+ { optsync = true;
+ optdepr = false;
+ optname = "depth for typeclasses proof search";
+ optkey = ["Typeclasses";"Depth"];
+ optread = get_typeclasses_depth;
+ optwrite = set_typeclasses_depth; }
+
+let pr_ev evs ev = Printer.pr_constr_env (Goal.V82.env evs ev) evs (Evarutil.nf_evar evs (Goal.V82.concl evs ev))
(** We transform the evars that are concerned by this resolution
(according to predicate p) into goals.
@@ -235,7 +303,7 @@ let unify_resolve_newcl poly flags =
{ enter = begin fun gls ((c, t, ctx),n,clenv) ->
let env = Proofview.Goal.env gls in
let concl = Proofview.Goal.concl gls in
- Proofview.Refine.refine ~unsafe:true { Sigma.run = fun sigma ->
+ Refine.refine ~unsafe:true { Sigma.run = fun sigma ->
let sigma = Sigma.to_evar_map sigma in
let sigma, term, ty =
if poly then
@@ -274,12 +342,16 @@ let clenv_of_prods poly nprods (c, clenv) gl =
else None
let with_prods nprods poly (c, clenv) f =
- Proofview.Goal.nf_enter { enter = begin fun gl ->
- match clenv_of_prods poly nprods (c, clenv) gl with
- | None -> Tacticals.New.tclZEROMSG (str"Not enough premisses")
- | Some (diff, clenv') -> f.enter gl (c, diff, clenv')
- end }
-
+ if get_typeclasses_limit_intros () then
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
+ match clenv_of_prods poly nprods (c, clenv) gl with
+ | None -> Tacticals.New.tclZEROMSG (str"Not enough premisses")
+ | Some (diff, clenv') -> f.enter gl (c, diff, clenv') end }
+ else Proofview.Goal.nf_enter
+ { enter = begin fun gl ->
+ if Int.equal nprods 0 then f.enter gl (c, None, clenv)
+ else Tacticals.New.tclZEROMSG (str"Not enough premisses") end }
+
let matches_pattern concl pat =
let matches env sigma =
match pat with
@@ -636,8 +708,8 @@ let new_hints_tac_gl only_classes hints info kont gl
let concl = Goal.concl gl in
let sigma = Goal.sigma gl in
let s = Sigma.to_evar_map sigma in
- if !typeclasses_debug then
- msg_debug (pr_depth info.search_depth ++ str": looking for " ++
+ if !typeclasses_debug > 0 then
+ Feedback.msg_debug (pr_depth info.search_depth ++ str": looking for " ++
Printer.pr_constr_env (Goal.env gl) s concl);
let poss = e_possible_resolve hints info.search_hints s concl in
let unique = is_unique env concl in
@@ -647,10 +719,11 @@ let new_hints_tac_gl only_classes hints info kont gl
let rec aux foundone e = function
| (tac, pat, b, name, pp) :: tl ->
let derivs = path_derivate info.search_cut name in
- (if !typeclasses_debug then
- msg_debug (pr_depth (!idx :: info.search_depth) ++ str": trying " ++
- Lazy.force pp ++
- str" on" ++ spc () ++ pr_ev s (Proofview.Goal.goal gl)));
+ (if !typeclasses_debug > 0 then
+ Feedback.msg_debug
+ (pr_depth (!idx :: info.search_depth) ++ str": trying " ++
+ Lazy.force pp ++
+ str" on" ++ spc () ++ pr_ev s (Proofview.Goal.goal gl)));
let tac_of i j =
Goal.nf_enter { enter = fun gl' ->
let sigma' = Goal.sigma gl' in
@@ -670,19 +743,21 @@ let new_hints_tac_gl only_classes hints info kont gl
search_hints = hints';
search_cut = derivs }
in
- if !typeclasses_debug then
- msg_debug (pr_depth (succ j :: i :: info.search_depth) ++ str" : " ++
- pr_ev s' (Proofview.Goal.goal gl'));
+ if !typeclasses_debug > 0 then
+ Feedback.msg_debug
+ (pr_depth (succ j :: i :: info.search_depth) ++ str" : " ++
+ pr_ev s' (Proofview.Goal.goal gl'));
kont info' }
in
let result () =
let i = !idx in
incr idx;
Proofview.numgoals >>= fun j ->
- (if !typeclasses_debug then
- msg_debug (pr_depth (i :: info.search_depth) ++ str": " ++ Lazy.force pp
- ++ str" on" ++ spc () ++ pr_ev s (Proofview.Goal.goal gl)
- ++ str", " ++ int j ++ str" subgoals");
+ (if !typeclasses_debug > 0 then
+ Feedback.msg_debug
+ (pr_depth (i :: info.search_depth) ++ str": " ++ Lazy.force pp
+ ++ str" on" ++ spc () ++ pr_ev s (Proofview.Goal.goal gl)
+ ++ str", " ++ int j ++ str" subgoals");
if j = 0 then
Proofview.tclUNIT ()
else Proofview.tclDISPATCH (List.init j (tac_of i)))
@@ -691,11 +766,12 @@ let new_hints_tac_gl only_classes hints info kont gl
else ortac (Proofview.tclBIND tac result)
(fun e' -> aux foundone (merge_exceptions e e') tl)
| [] ->
- if foundone == None && !typeclasses_debug then
- msg_debug (pr_depth info.search_depth ++ str": no match for " ++
- Printer.pr_constr_env (Goal.env gl) s concl ++
- spc () ++ str ", " ++ int (List.length poss) ++
- str" possibilities");
+ if foundone == None && !typeclasses_debug > 0 then
+ Feedback.msg_debug
+ (pr_depth info.search_depth ++ str": no match for " ++
+ Printer.pr_constr_env (Goal.env gl) s concl ++
+ spc () ++ str ", " ++ int (List.length poss) ++
+ str" possibilities");
match e with
| (ReachedLimitEx,ie) -> Proofview.tclZERO ~info:ie ReachedLimitEx
| (_,ie) -> Proofview.tclZERO ~info:ie NotApplicableEx
@@ -736,9 +812,10 @@ let intro_tac' only_classes info kont =
let rec eauto_tac' only_classes hints limit depth =
let kont info =
Proofview.numgoals >>= fun i ->
- if !typeclasses_debug then
- msg_debug (str"calling eauto recursively at depth " ++ int (succ depth)
- ++ str" on " ++ int i ++ str" subgoals");
+ if !typeclasses_debug > 1 then
+ Feedback.msg_debug
+ (str"calling eauto recursively at depth " ++ int (succ depth)
+ ++ str" on " ++ int i ++ str" subgoals");
eauto_tac' only_classes hints limit (succ depth) info
in
fun info ->
@@ -863,7 +940,7 @@ let hints_tac hints =
(match res with
| None -> aux i foundone tl
| Some {it = gls; sigma = s';} ->
- if !typeclasses_debug then
+ if !typeclasses_debug > 0 then
Feedback.msg_debug (pr_depth (i :: info.auto_depth) ++ str": " ++ Lazy.force pp
++ str" on" ++ spc () ++ pr_ev s gl);
let sgls =
@@ -891,13 +968,15 @@ let hints_tac hints =
let gls' = List.map_i
(fun j (evar, g) ->
let info =
- { info with auto_depth = j :: i :: info.auto_depth; auto_last_tac = pp;
+ { info with
+ auto_depth = j :: i :: info.auto_depth;
+ auto_last_tac = pp;
is_evar = evar;
hints =
if b && not (Environ.eq_named_context_val (Goal.V82.hyps s' g)
- (Goal.V82.hyps s' gl))
+ (Goal.V82.hyps s' gl))
then make_autogoal_hints info.only_classes
- ~st:(Hint_db.transparent_state info.hints) {it = g; sigma = s';}
+ ~st:(Hint_db.transparent_state info.hints) {it = g; sigma = s';}
else info.hints;
auto_cut = derivs }
in g, info) 1 newgls in
@@ -912,7 +991,7 @@ let hints_tac hints =
else true
in
let e' = match foundone with None -> e | Some e' -> merge_failures e e' in
- if !typeclasses_debug then
+ if !typeclasses_debug > 0 then
Feedback.msg_debug
((if do_backtrack then str"Backtracking after "
else str "Not backtracking after ")
@@ -922,7 +1001,7 @@ let hints_tac hints =
in
sk glsv fk')
| [] ->
- if foundone == None && !typeclasses_debug then
+ if foundone == None && !typeclasses_debug > 0 then
Feedback.msg_debug (pr_depth info.auto_depth ++ str": no match for " ++
Printer.pr_constr_env (Goal.V82.env s gl) s concl ++
spc () ++ str ", " ++ int (List.length poss) ++ str" possibilities");
@@ -995,10 +1074,12 @@ let fix_iterative_limit limit (t : 'a tac) : 'a tac =
else or_tac (fix_limit depth t) { skft = fun sk fk -> (aux (succ depth)).skft sk fk }
in aux 1
-let make_autogoal ?(only_classes=true) ?(unique=false) ?(st=full_transparent_state) cut ev g =
+let make_autogoal ?(only_classes=true) ?(unique=false) ?(st=full_transparent_state)
+ cut ev g =
let hints = make_autogoal_hints only_classes ~st g in
(g.it, { hints = hints ; is_evar = ev; unique = unique;
- only_classes = only_classes; auto_depth = []; auto_last_tac = lazy (str"none");
+ only_classes = only_classes; auto_depth = [];
+ auto_last_tac = lazy (str"none");
auto_path = []; auto_cut = cut })
@@ -1062,7 +1143,8 @@ let resolve_all_evars_once debug limit unique p evd =
real_eauto ?limit unique (Hint_db.transparent_state db) [db] p evd
let eauto ?(only_classes=true) ?st ?limit hints g =
- let gl = { it = make_autogoal ~only_classes ?st (cut_of_hints hints) None g; sigma = project g; } in
+ let gl = { it = make_autogoal ~only_classes ?st
+ (cut_of_hints hints) None g; sigma = project g; } in
match run_tac (eauto_tac ?limit hints) gl with
| None -> raise Not_found
| Some {it = goals; sigma = s; } ->
@@ -1233,51 +1315,14 @@ let resolve_typeclass_evars debug m unique env evd filter split fail =
in
resolve_all_evars debug m unique env (initial_select_evars filter) evd split fail
-let solve_inst debug depth env evd filter unique split fail =
- resolve_typeclass_evars debug depth unique env evd filter split fail
+let solve_inst env evd filter unique split fail =
+ resolve_typeclass_evars
+ (get_typeclasses_debug ())
+ (get_typeclasses_depth ())
+ unique env evd filter split fail
let _ =
- Typeclasses.solve_instantiations_problem :=
- solve_inst false !typeclasses_depth
-
-let set_typeclasses_debug d = (:=) typeclasses_debug d;
- Typeclasses.solve_instantiations_problem := solve_inst d !typeclasses_depth
-
-let get_typeclasses_debug () = !typeclasses_debug
-
-let set_typeclasses_depth d = (:=) typeclasses_depth d;
- Typeclasses.solve_instantiations_problem := solve_inst !typeclasses_debug !typeclasses_depth
-
-let get_typeclasses_depth () = !typeclasses_depth
-
-open Goptions
-
-let set_typeclasses_debug =
- declare_bool_option
- { optsync = true;
- optdepr = false;
- optname = "debug output for typeclasses proof search";
- optkey = ["Typeclasses";"Debug"];
- optread = get_typeclasses_debug;
- optwrite = set_typeclasses_debug; }
-
-let set_typeclasses_debug =
- declare_bool_option
- { optsync = true;
- optdepr = false;
- optname = "debug output for typeclasses proof search";
- optkey = ["Debug";"Typeclasses"];
- optread = get_typeclasses_debug;
- optwrite = set_typeclasses_debug; }
-
-let set_typeclasses_depth =
- declare_int_option
- { optsync = true;
- optdepr = false;
- optname = "depth for typeclasses proof search";
- optkey = ["Typeclasses";"Depth"];
- optread = get_typeclasses_depth;
- optwrite = set_typeclasses_depth; }
+ Typeclasses.solve_instantiations_problem := solve_inst
let typeclasses_eauto ?(only_classes=false) ?(st=full_transparent_state) dbs gl =
try