summaryrefslogtreecommitdiff
path: root/tactics/tacinterp.ml
diff options
context:
space:
mode:
Diffstat (limited to 'tactics/tacinterp.ml')
-rw-r--r--tactics/tacinterp.ml1516
1 files changed, 818 insertions, 698 deletions
diff --git a/tactics/tacinterp.ml b/tactics/tacinterp.ml
index 5c891c58..87c88b9d 100644
--- a/tactics/tacinterp.ml
+++ b/tactics/tacinterp.ml
@@ -6,14 +6,13 @@
(* * GNU Lesser General Public License Version 2.1 *)
(************************************************************************)
-(* $Id: tacinterp.ml 13130 2010-06-13 18:45:09Z herbelin $ *)
+(* $Id$ *)
open Constrintern
open Closure
open RedFlags
open Declarations
open Entries
-open Dyn
open Libobject
open Pattern
open Matching
@@ -26,6 +25,7 @@ open Names
open Nameops
open Libnames
open Nametab
+open Smartlocate
open Pfedit
open Proof_type
open Refiner
@@ -46,16 +46,17 @@ open Inductiveops
open Syntax_def
open Pretyping
open Pretyping.Default
+open Extrawit
open Pcoq
let safe_msgnl s =
- try msgnl s with e ->
- msgnl
+ try msgnl s with e ->
+ msgnl
(str "bug in the debugger: " ++
str "an exception is raised while printing debug information")
let error_syntactic_metavariables_not_allowed loc =
- user_err_loc
+ user_err_loc
(loc,"out_ident",
str "Syntactic metavariables allowed only in quotations.")
@@ -74,14 +75,15 @@ type ltac_type =
type value =
| VRTactic of (goal list sigma * validation) (* For Match results *)
(* Not a true value *)
- | VFun of ltac_trace * (identifier*value) list *
+ | VFun of ltac_trace * (identifier*value) list *
identifier option list * glob_tactic_expr
| VVoid
| VInteger of int
| VIntroPattern of intro_pattern_expr (* includes idents which are not *)
(* bound as in "Intro H" but which may be bound *)
(* later, as in "tac" in "Intro H; tac" *)
- | VConstr of constr (* includes idents known to be bound and references *)
+ | VConstr of constr_under_binders
+ (* includes idents known to be bound and references *)
| VConstr_context of constr
| VList of value list
| VRec of (identifier*value) list ref * glob_tactic_expr
@@ -93,13 +95,13 @@ let catch_error call_trace tac g =
| LtacLocated _ as e -> raise e
| Stdpp.Exc_located (_,LtacLocated _) as e -> raise e
| e ->
- let (loc',c),tail = list_sep_last call_trace in
+ let (nrep,loc',c),tail = list_sep_last call_trace in
let loc,e' = match e with Stdpp.Exc_located(loc,e) -> loc,e | _ ->dloc,e in
if tail = [] then
let loc = if loc = dloc then loc' else loc in
raise (Stdpp.Exc_located(loc,e'))
else
- raise (Stdpp.Exc_located(loc',LtacLocated((c,tail,loc),e')))
+ raise (Stdpp.Exc_located(loc',LtacLocated((nrep,c,tail,loc),e')))
(* Signature for interpretation: val_interp and interpretation functions *)
type interp_sign =
@@ -114,9 +116,6 @@ let check_is_value = function
error "Immediate match producing tactics not allowed in local definitions."
| _ -> ()
-(* For tactic_of_value *)
-exception NotTactic
-
(* Gives the constr corresponding to a Constr_context tactic_arg *)
let constr_of_VConstr_context = function
| VConstr_context c -> c
@@ -128,7 +127,10 @@ let rec pr_value env = function
| VVoid -> str "()"
| VInteger n -> int n
| VIntroPattern ipat -> pr_intro_pattern (dloc,ipat)
- | VConstr c | VConstr_context c ->
+ | VConstr c ->
+ (match env with Some env ->
+ pr_lconstr_under_binders_env env c | _ -> str "a term")
+ | VConstr_context c ->
(match env with Some env -> pr_lconstr_env env c | _ -> str "a term")
| (VRTactic _ | VFun _ | VRec _) -> str "a tactic"
| VList [] -> str "an empty list"
@@ -136,21 +138,21 @@ let rec pr_value env = function
str "a list (first element is " ++ pr_value env a ++ str")"
(* Transforms an id into a constr if possible, or fails *)
-let constr_of_id env id =
+let constr_of_id env id =
construct_reference (Environ.named_context env) id
(* To embed tactics *)
let ((tactic_in : (interp_sign -> glob_tactic_expr) -> Dyn.t),
(tactic_out : Dyn.t -> (interp_sign -> glob_tactic_expr))) =
- create "tactic"
+ Dyn.create "tactic"
let ((value_in : value -> Dyn.t),
- (value_out : Dyn.t -> value)) = create "value"
+ (value_out : Dyn.t -> value)) = Dyn.create "value"
let valueIn t = TacDynamic (dummy_loc,value_in t)
let valueOut = function
| TacDynamic (_,d) ->
- if (tag d) = "value" then
+ if (Dyn.tag d) = "value" then
value_out d
else
anomalylabstrm "valueOut" (str "Dynamic tag should be value")
@@ -176,11 +178,6 @@ let find_reference env qid =
-> VarRef id
| _ -> Nametab.locate qid
-let error_not_evaluable s =
- errorlabstrm "evalref_of_ref"
- (str "Cannot coerce" ++ spc () ++ s ++ spc () ++
- str "to an evaluable reference.")
-
(* Table of "pervasives" macros tactics (e.g. auto, simpl, etc.) *)
let atomic_mactab = ref Idmap.empty
let add_primitive_tactic s tac =
@@ -205,8 +202,8 @@ let _ =
"eleft", TacLeft(true,NoBindings);
"right", TacRight(false,NoBindings);
"eright", TacRight(true,NoBindings);
- "split", TacSplit(false,false,NoBindings);
- "esplit", TacSplit(true,false,NoBindings);
+ "split", TacSplit(false,false,[NoBindings]);
+ "esplit", TacSplit(true,false,[NoBindings]);
"constructor", TacAnyConstructor (false,None);
"econstructor", TacAnyConstructor (true,None);
"reflexivity", TacReflexivity;
@@ -218,7 +215,7 @@ let _ =
"fail", TacFail(ArgArg 0,[]);
"fresh", TacArg(TacFreshId [])
]
-
+
let lookup_atomic id = Idmap.find id !atomic_mactab
let is_atomic_kn kn =
let (_,_,l) = repr_kn kn in
@@ -236,9 +233,7 @@ let _ =
Summary.declare_summary "tactic-definition"
{ Summary.freeze_function = freeze;
Summary.unfreeze_function = unfreeze;
- Summary.init_function = init;
- Summary.survive_module = false;
- Summary.survive_section = false }
+ Summary.init_function = init }
(* Tactics table (TacExtend). *)
@@ -246,7 +241,7 @@ let tac_tab = Hashtbl.create 17
let add_tactic s t =
if Hashtbl.mem tac_tab s then
- errorlabstrm ("Refiner.add_tactic: ")
+ errorlabstrm ("Refiner.add_tactic: ")
(str ("Cannot redeclare tactic "^s^"."));
Hashtbl.add tac_tab s t
@@ -258,9 +253,9 @@ let overwriting_add_tactic s t =
Hashtbl.add tac_tab s t
let lookup_tactic s =
- try
+ try
Hashtbl.find tac_tab s
- with Not_found ->
+ with Not_found ->
errorlabstrm "Refiner.lookup_tactic"
(str"The tactic " ++ str s ++ str" is not installed.")
(*
@@ -279,7 +274,7 @@ type glob_sign = {
type interp_genarg_type =
(glob_sign -> raw_generic_argument -> glob_generic_argument) *
- (interp_sign -> goal sigma -> glob_generic_argument ->
+ (interp_sign -> goal sigma -> glob_generic_argument ->
typed_generic_argument) *
(substitution -> glob_generic_argument -> glob_generic_argument)
@@ -287,24 +282,34 @@ let extragenargtab =
ref (Gmap.empty : (string,interp_genarg_type) Gmap.t)
let add_interp_genarg id f =
extragenargtab := Gmap.add id f !extragenargtab
-let lookup_genarg id =
+let lookup_genarg id =
try Gmap.find id !extragenargtab
- with Not_found -> failwith ("No interpretation function found for entry "^id)
+ with Not_found ->
+ let msg = "No interpretation function found for entry " ^ id in
+ warning msg;
+ let f = (fun _ _ -> failwith msg), (fun _ _ _ -> failwith msg), (fun _ a -> a) in
+ add_interp_genarg id f;
+ f
+
let lookup_genarg_glob id = let (f,_,_) = lookup_genarg id in f
let lookup_interp_genarg id = let (_,f,_) = lookup_genarg id in f
let lookup_genarg_subst id = let (_,_,f) = lookup_genarg id in f
+let push_trace (loc,ck) = function
+ | (n,loc',ck')::trl when ck=ck' -> (n+1,loc,ck)::trl
+ | trl -> (1,loc,ck)::trl
+
let propagate_trace ist loc id = function
| VFun (_,lfun,it,b) ->
let t = if it=[] then b else TacFun (it,b) in
- VFun ((loc,LtacVarCall (id,t))::ist.trace,lfun,it,b)
+ VFun (push_trace(loc,LtacVarCall (id,t)) ist.trace,lfun,it,b)
| x -> x
(* Dynamically check that an argument is a tactic *)
let coerce_to_tactic loc id = function
| VFun _ | VRTactic _ as a -> a
- | _ -> user_err_loc
+ | _ -> user_err_loc
(loc, "", str "Variable " ++ pr_id id ++ str " should be bound to a tactic.")
(*****************)
@@ -313,23 +318,23 @@ let coerce_to_tactic loc id = function
(* We have identifier <| global_reference <| constr *)
-let find_ident id sign =
- List.mem id (fst sign.ltacvars) or
- List.mem id (ids_of_named_context (Environ.named_context sign.genv))
+let find_ident id ist =
+ List.mem id (fst ist.ltacvars) or
+ List.mem id (ids_of_named_context (Environ.named_context ist.genv))
-let find_recvar qid sign = List.assoc qid sign.ltacrecvars
+let find_recvar qid ist = List.assoc qid ist.ltacrecvars
(* a "var" is a ltac var or a var introduced by an intro tactic *)
-let find_var id sign = List.mem id (fst sign.ltacvars)
+let find_var id ist = List.mem id (fst ist.ltacvars)
(* a "ctxvar" is a var introduced by an intro tactic (Intro/LetTac/...) *)
-let find_ctxvar id sign = List.mem id (snd sign.ltacvars)
+let find_ctxvar id ist = List.mem id (snd ist.ltacvars)
(* a "ltacvar" is an ltac var (Let-In/Fun/...) *)
-let find_ltacvar id sign = find_var id sign & not (find_ctxvar id sign)
+let find_ltacvar id ist = find_var id ist & not (find_ctxvar id ist)
-let find_hyp id sign =
- List.mem id (ids_of_named_context (Environ.named_context sign.genv))
+let find_hyp id ist =
+ List.mem id (ids_of_named_context (Environ.named_context ist.genv))
(* Globalize a name introduced by Intro/LetTac/... ; it is allowed to *)
(* be fresh in which case it is binding later on *)
@@ -348,7 +353,7 @@ let vars_of_ist (lfun,_,_,env) =
let get_current_context () =
try Pfedit.get_current_goal_context ()
- with e when Logic.catchable_exception e ->
+ with e when Logic.catchable_exception e ->
(Evd.empty, Global.env())
let strict_check = ref false
@@ -370,17 +375,7 @@ let intern_or_var ist = function
| ArgVar locid -> ArgVar (intern_hyp ist locid)
| ArgArg _ as x -> x
-let loc_of_by_notation f = function
- | AN c -> f c
- | ByNotation (loc,s,_) -> loc
-
-let destIndRef = function IndRef ind -> ind | _ -> failwith "destIndRef"
-
-let intern_inductive_or_by_notation = function
- | AN r -> Nametab.inductive_of_reference r
- | ByNotation (loc,ntn,sc) ->
- destIndRef (Notation.interp_notation_as_global_reference loc
- (function IndRef ind -> true | _ -> false) ntn sc)
+let intern_inductive_or_by_notation = smart_global_inductive
let intern_inductive ist = function
| AN (Ident (loc,id)) when find_var id ist -> ArgVar (loc,id)
@@ -388,10 +383,10 @@ let intern_inductive ist = function
let intern_global_reference ist = function
| Ident (loc,id) when find_var id ist -> ArgVar (loc,id)
- | r ->
+ | r ->
let loc,_ as lqid = qualid_of_reference r in
try ArgArg (loc,locate_global_with_alias lqid)
- with Not_found ->
+ with Not_found ->
error_global_not_found_loc lqid
let intern_ltac_variable ist = function
@@ -486,7 +481,9 @@ let rec intern_intro_pattern lf ist = function
loc, IntroOrAndPattern (intern_or_and_intro_pattern lf ist l)
| loc, IntroIdentifier id ->
loc, IntroIdentifier (intern_ident lf ist id)
- | loc, (IntroWildcard | IntroAnonymous | IntroFresh _ | IntroRewrite _)
+ | loc, IntroFresh id ->
+ loc, IntroFresh (intern_ident lf ist id)
+ | loc, (IntroWildcard | IntroAnonymous | IntroRewrite _ | IntroForthcoming _)
as x -> x
and intern_or_and_intro_pattern lf ist =
@@ -497,22 +494,22 @@ let intern_quantified_hypothesis ist = function
| NamedHyp id ->
(* Uncomment to disallow "intros until n" in ltac when n is not bound *)
NamedHyp ((*snd (intern_hyp ist (dloc,*)id(* ))*))
-
+
let intern_binding_name ist x =
(* We use identifier both for variables and binding names *)
- (* Todo: consider the body of the lemma to which the binding refer
+ (* Todo: consider the body of the lemma to which the binding refer
and if a term w/o ltac vars, check the name is indeed quantified *)
x
-let intern_constr_gen isarity {ltacvars=lfun; gsigma=sigma; genv=env} c =
+let intern_constr_gen allow_patvar isarity {ltacvars=lfun; gsigma=sigma; genv=env} c =
let warn = if !strict_check then fun x -> x else Constrintern.for_grammar in
- let c' =
- warn (Constrintern.intern_gen isarity ~ltacvars:(fst lfun,[]) sigma env) c
+ let c' =
+ warn (Constrintern.intern_gen isarity ~allow_patvar ~ltacvars:(fst lfun,[]) sigma env) c
in
(c',if !strict_check then None else Some c)
-let intern_constr = intern_constr_gen false
-let intern_type = intern_constr_gen true
+let intern_constr = intern_constr_gen false false
+let intern_type = intern_constr_gen false true
(* Globalize bindings *)
let intern_binding ist (loc,b,c) =
@@ -545,38 +542,33 @@ let intern_induction_arg ist = function
else
ElimOnIdent (loc,id)
-let evaluable_of_global_reference = function
- | ConstRef c -> EvalConstRef c
- | VarRef c -> EvalVarRef c
- | r -> error_not_evaluable (pr_global r)
-
let short_name = function
| AN (Ident (loc,id)) when not !strict_check -> Some (loc,id)
| _ -> None
-let interp_global_reference r =
+let intern_evaluable_global_reference ist r =
let lqid = qualid_of_reference r in
- try locate_global_with_alias lqid
+ try evaluable_of_global_reference ist.genv (locate_global_with_alias lqid)
with Not_found ->
- match r with
- | Ident (loc,id) when not !strict_check -> VarRef id
+ match r with
+ | Ident (loc,id) when not !strict_check -> EvalVarRef id
| _ -> error_global_not_found_loc lqid
-let intern_evaluable_reference_or_by_notation = function
- | AN r -> evaluable_of_global_reference (interp_global_reference r)
+let intern_evaluable_reference_or_by_notation ist = function
+ | AN r -> intern_evaluable_global_reference ist r
| ByNotation (loc,ntn,sc) ->
- evaluable_of_global_reference
+ evaluable_of_global_reference ist.genv
(Notation.interp_notation_as_global_reference loc
(function ConstRef _ | VarRef _ -> true | _ -> false) ntn sc)
-(* Globalizes a reduction expression *)
+(* Globalize a reduction expression *)
let intern_evaluable ist = function
| AN (Ident (loc,id)) when find_ltacvar id ist -> ArgVar (loc,id)
| AN (Ident (_,id)) when
(not !strict_check & find_hyp id ist) or find_ctxvar id ist ->
ArgArg (EvalVarRef id, None)
| r ->
- let e = intern_evaluable_reference_or_by_notation r in
+ let e = intern_evaluable_reference_or_by_notation ist r in
let na = short_name r in
ArgArg (e,na)
@@ -587,15 +579,31 @@ let intern_flag ist red =
let intern_constr_with_occurrences ist (l,c) = (l,intern_constr ist c)
+let intern_constr_pattern ist ltacvars pc =
+ let metas,pat =
+ Constrintern.intern_constr_pattern ist.gsigma ist.genv ~ltacvars pc in
+ let c = intern_constr_gen true false ist pc in
+ metas,(c,pat)
+
+let intern_typed_pattern ist p =
+ let dummy_pat = PRel 0 in
+ (* we cannot ensure in non strict mode that the pattern is closed *)
+ (* keeping a constr_expr copy is too complicated and we want anyway to *)
+ (* type it, so we remember the pattern as a rawconstr only *)
+ (intern_constr_gen true false ist p,dummy_pat)
+
+let intern_typed_pattern_with_occurrences ist (l,p) =
+ (l,intern_typed_pattern ist p)
+
let intern_red_expr ist = function
| Unfold l -> Unfold (List.map (intern_unfold ist) l)
| Fold l -> Fold (List.map (intern_constr ist) l)
| Cbv f -> Cbv (intern_flag ist f)
| Lazy f -> Lazy (intern_flag ist f)
| Pattern l -> Pattern (List.map (intern_constr_with_occurrences ist) l)
- | Simpl o -> Simpl (Option.map (intern_constr_with_occurrences ist) o)
+ | Simpl o -> Simpl (Option.map (intern_typed_pattern_with_occurrences ist) o)
| (Red _ | Hnf | ExtraRedExpr _ | CbvVm as r ) -> r
-
+
let intern_in_hyp_as ist lf (id,ipat) =
(intern_hyp_or_metaid ist id, Option.map (intern_intro_pattern lf ist) ipat)
@@ -616,15 +624,15 @@ let intern_hyp_location ist (((b,occs),id),hl) =
(((b,List.map (intern_or_var ist) occs),intern_hyp_or_metaid ist id), hl)
(* Reads a pattern *)
-let intern_pattern sigma env ?(as_type=false) lfun = function
+let intern_pattern ist ?(as_type=false) lfun = function
| Subterm (b,ido,pc) ->
let ltacvars = (lfun,[]) in
- let (metas,pat) = intern_constr_pattern sigma env ~ltacvars pc in
- ido, metas, Subterm (b,ido,pat)
+ let (metas,pc) = intern_constr_pattern ist ltacvars pc in
+ ido, metas, Subterm (b,ido,pc)
| Term pc ->
let ltacvars = (lfun,[]) in
- let (metas,pat) = intern_constr_pattern sigma env ~as_type ~ltacvars pc in
- None, metas, Term pat
+ let (metas,pc) = intern_constr_pattern ist ltacvars pc in
+ None, metas, Term pc
let intern_constr_may_eval ist = function
| ConstrEval (r,c) -> ConstrEval (intern_red_expr ist r,intern_constr ist c)
@@ -640,10 +648,10 @@ let declare_xml_printer f = print_xml_term := f
let internalise_tacarg ch = G_xml.parse_tactic_arg ch
let extern_tacarg ch env sigma = function
- | VConstr c -> !print_xml_term ch env sigma c
+ | VConstr ([],c) -> !print_xml_term ch env sigma c
| VRTactic _ | VFun _ | VVoid | VInteger _ | VConstr_context _
- | VIntroPattern _ | VRec _ | VList _ ->
- error "Only externing of terms is implemented."
+ | VIntroPattern _ | VRec _ | VList _ | VConstr _ ->
+ error "Only externing of closed terms is implemented."
let extern_request ch req gl la =
output_string ch "<REQUEST req=\""; output_string ch req;
@@ -651,24 +659,33 @@ let extern_request ch req gl la =
List.iter (pf_apply (extern_tacarg ch) gl) la;
output_string ch "</REQUEST>\n"
+let value_of_ident id = VIntroPattern (IntroIdentifier id)
+
+let extend_values_with_bindings (ln,lm) lfun =
+ let lnames = List.map (fun (id,id') ->(id,value_of_ident id')) ln in
+ let lmatch = List.map (fun (id,(ids,c)) -> (id,VConstr (ids,c))) lm in
+ (* For compatibility, bound variables are visible only if no other
+ binding of the same name exists *)
+ lmatch@lfun@lnames
+
(* Reads the hypotheses of a "match goal" rule *)
-let rec intern_match_goal_hyps sigma env lfun = function
+let rec intern_match_goal_hyps ist lfun = function
| (Hyp ((_,na) as locna,mp))::tl ->
- let ido, metas1, pat = intern_pattern sigma env ~as_type:true lfun mp in
- let lfun, metas2, hyps = intern_match_goal_hyps sigma env lfun tl in
+ let ido, metas1, pat = intern_pattern ist ~as_type:true lfun mp in
+ let lfun, metas2, hyps = intern_match_goal_hyps ist lfun tl in
let lfun' = name_cons na (Option.List.cons ido lfun) in
lfun', metas1@metas2, Hyp (locna,pat)::hyps
| (Def ((_,na) as locna,mv,mp))::tl ->
- let ido, metas1, patv = intern_pattern sigma env ~as_type:false lfun mv in
- let ido', metas2, patt = intern_pattern sigma env ~as_type:true lfun mp in
- let lfun, metas3, hyps = intern_match_goal_hyps sigma env lfun tl in
+ let ido, metas1, patv = intern_pattern ist ~as_type:false lfun mv in
+ let ido', metas2, patt = intern_pattern ist ~as_type:true lfun mp in
+ let lfun, metas3, hyps = intern_match_goal_hyps ist lfun tl in
let lfun' = name_cons na (Option.List.cons ido' (Option.List.cons ido lfun)) in
lfun', metas1@metas2@metas3, Def (locna,patv,patt)::hyps
| [] -> lfun, [], []
(* Utilities *)
let extract_let_names lrc =
- List.fold_right
+ List.fold_right
(fun ((loc,name),_) l ->
if List.mem name l then
user_err_loc
@@ -684,7 +701,7 @@ let clause_app f = function
(* Globalizes tactics : raw_tactic_expr -> glob_tactic_expr *)
let rec intern_atomic lf ist x =
- match (x:raw_atomic_tactic_expr) with
+ match (x:raw_atomic_tactic_expr) with
(* Basic tactics *)
| TacIntroPattern l ->
TacIntroPattern (List.map (intern_intro_pattern lf ist) l)
@@ -717,7 +734,7 @@ let rec intern_atomic lf ist x =
| TacAssert (otac,ipat,c) ->
TacAssert (Option.map (intern_tactic ist) otac,
Option.map (intern_intro_pattern lf ist) ipat,
- intern_constr_gen (otac<>None) ist c)
+ intern_constr_gen false (otac<>None) ist c)
| TacGeneralize cl ->
TacGeneralize (List.map (fun (c,na) ->
intern_constr_with_occurrences ist c,
@@ -744,13 +761,13 @@ let rec intern_atomic lf ist x =
(* Derived basic tactics *)
| TacSimpleInductionDestruct (isrec,h) ->
TacSimpleInductionDestruct (isrec,intern_quantified_hypothesis ist h)
- | TacInductionDestruct (ev,isrec,l) ->
- TacInductionDestruct (ev,isrec,List.map (fun (lc,cbo,(ipato,ipats),cls) ->
+ | TacInductionDestruct (ev,isrec,(l,cls)) ->
+ TacInductionDestruct (ev,isrec,(List.map (fun (lc,cbo,(ipato,ipats)) ->
(List.map (intern_induction_arg ist) lc,
Option.map (intern_constr_with_bindings ist) cbo,
(Option.map (intern_intro_pattern lf ist) ipato,
- Option.map (intern_intro_pattern lf ist) ipats),
- Option.map (clause_app (intern_hyp_location ist)) cls)) l)
+ Option.map (intern_intro_pattern lf ist) ipats))) l,
+ Option.map (clause_app (intern_hyp_location ist)) cls))
| TacDoubleInduction (h1,h2) ->
let h1 = intern_quantified_hypothesis ist h1 in
let h2 = intern_quantified_hypothesis ist h2 in
@@ -767,40 +784,43 @@ let rec intern_atomic lf ist x =
| TacClearBody l -> TacClearBody (List.map (intern_hyp_or_metaid ist) l)
| TacMove (dep,id1,id2) ->
TacMove (dep,intern_hyp_or_metaid ist id1,intern_move_location ist id2)
- | TacRename l ->
- TacRename (List.map (fun (id1,id2) ->
- intern_hyp_or_metaid ist id1,
+ | TacRename l ->
+ TacRename (List.map (fun (id1,id2) ->
+ intern_hyp_or_metaid ist id1,
intern_hyp_or_metaid ist id2) l)
| TacRevert l -> TacRevert (List.map (intern_hyp_or_metaid ist) l)
-
+
(* Constructors *)
| TacLeft (ev,bl) -> TacLeft (ev,intern_bindings ist bl)
| TacRight (ev,bl) -> TacRight (ev,intern_bindings ist bl)
- | TacSplit (ev,b,bl) -> TacSplit (ev,b,intern_bindings ist bl)
+ | TacSplit (ev,b,bll) -> TacSplit (ev,b,List.map (intern_bindings ist) bll)
| TacAnyConstructor (ev,t) -> TacAnyConstructor (ev,Option.map (intern_tactic ist) t)
| TacConstructor (ev,n,bl) -> TacConstructor (ev,n,intern_bindings ist bl)
(* Conversion *)
| TacReduce (r,cl) ->
TacReduce (intern_red_expr ist r, clause_app (intern_hyp_location ist) cl)
- | TacChange (occl,c,cl) ->
- TacChange (Option.map (intern_constr_with_occurrences ist) occl,
- (if occl = None & (cl.onhyps = None or cl.onhyps = Some []) &
+ | TacChange (None,c,cl) ->
+ TacChange (None,
+ (if (cl.onhyps = None or cl.onhyps = Some []) &
(cl.concl_occs = all_occurrences_expr or
cl.concl_occs = no_occurrences_expr)
then intern_type ist c else intern_constr ist c),
clause_app (intern_hyp_location ist) cl)
+ | TacChange (Some p,c,cl) ->
+ TacChange (Some (intern_typed_pattern ist p),intern_constr ist c,
+ clause_app (intern_hyp_location ist) cl)
(* Equivalence relations *)
| TacReflexivity -> TacReflexivity
- | TacSymmetry idopt ->
+ | TacSymmetry idopt ->
TacSymmetry (clause_app (intern_hyp_location ist) idopt)
- | TacTransitivity c -> TacTransitivity (intern_constr ist c)
+ | TacTransitivity c -> TacTransitivity (Option.map (intern_constr ist) c)
(* Equality and inversion *)
- | TacRewrite (ev,l,cl,by) ->
- TacRewrite
- (ev,
+ | TacRewrite (ev,l,cl,by) ->
+ TacRewrite
+ (ev,
List.map (fun (b,m,c) -> (b,m,intern_constr_with_bindings ist c)) l,
clause_app (intern_hyp_location ist) cl,
Option.map (intern_tactic ist) by)
@@ -827,7 +847,7 @@ and intern_tactic_seq ist = function
| TacLetIn (isrec,l,u) ->
let (l1,l2) = ist.ltacvars in
let ist' = { ist with ltacvars = (extract_let_names l @ l1, l2) } in
- let l = List.map (fun (n,b) ->
+ let l = List.map (fun (n,b) ->
(n,intern_tacarg !strict_check (if isrec then ist' else ist) b)) l in
ist.ltacvars, TacLetIn (isrec,l,intern_tactic ist' u)
| TacMatchGoal (lz,lr,lmr) ->
@@ -835,7 +855,7 @@ and intern_tactic_seq ist = function
| TacMatch (lz,c,lmr) ->
ist.ltacvars, TacMatch (lz,intern_tactic ist c,intern_match_rule ist lmr)
| TacId l -> ist.ltacvars, TacId (intern_message ist l)
- | TacFail (n,l) ->
+ | TacFail (n,l) ->
ist.ltacvars, TacFail (intern_or_var ist n,intern_message ist l)
| TacProgress tac -> ist.ltacvars, TacProgress (intern_tactic ist tac)
| TacAbstract (tac,s) -> ist.ltacvars, TacAbstract (intern_tactic ist tac,s)
@@ -854,7 +874,7 @@ and intern_tactic_seq ist = function
let ist' = { ist with ltacvars = lfun' } in
(* Que faire en cas de (tac complexe avec Match et Thens; tac2) ?? *)
lfun', TacThens (t, List.map (intern_tactic ist') tl)
- | TacDo (n,tac) ->
+ | TacDo (n,tac) ->
ist.ltacvars, TacDo (intern_or_var ist n,intern_tactic ist tac)
| TacTry tac -> ist.ltacvars, TacTry (intern_tactic ist tac)
| TacInfo tac -> ist.ltacvars, TacInfo (intern_tactic ist tac)
@@ -866,7 +886,7 @@ and intern_tactic_seq ist = function
| TacComplete tac -> ist.ltacvars, TacComplete (intern_tactic ist tac)
| TacArg a -> ist.ltacvars, TacArg (intern_tacarg true ist a)
-and intern_tactic_fun ist (var,body) =
+and intern_tactic_fun ist (var,body) =
let (l1,l2) = ist.ltacvars in
let lfun' = List.rev_append (Option.List.flatten var) l1 in
(var,intern_tactic { ist with ltacvars = (lfun',l2) } body)
@@ -874,7 +894,7 @@ and intern_tactic_fun ist (var,body) =
and intern_tacarg strict ist = function
| TacVoid -> TacVoid
| Reference r -> intern_non_tactic_reference strict ist r
- | IntroPattern ipat ->
+ | IntroPattern ipat ->
let lf = ref([],[]) in (*How to know what names the intropattern binds?*)
IntroPattern (intern_intro_pattern lf ist ipat)
| Integer n -> Integer n
@@ -891,12 +911,12 @@ and intern_tacarg strict ist = function
TacCall (loc,
intern_applied_tactic_reference ist f,
List.map (intern_tacarg !strict_check ist) l)
- | TacExternal (loc,com,req,la) ->
+ | TacExternal (loc,com,req,la) ->
TacExternal (loc,com,req,List.map (intern_tacarg !strict_check ist) la)
| TacFreshId x -> TacFreshId (List.map (intern_or_var ist) x)
| Tacexp t -> Tacexp (intern_tactic ist t)
| TacDynamic(loc,t) as x ->
- (match tag t with
+ (match Dyn.tag t with
| "tactic" | "value" | "constr" -> x
| s -> anomaly_loc (loc, "",
str "Unknown dynamic: <" ++ str s ++ str ">"))
@@ -907,8 +927,8 @@ and intern_match_rule ist = function
All (intern_tactic ist tc) :: (intern_match_rule ist tl)
| (Pat (rl,mp,tc))::tl ->
let {ltacvars=(lfun,l2); gsigma=sigma; genv=env} = ist in
- let lfun',metas1,hyps = intern_match_goal_hyps sigma env lfun rl in
- let ido,metas2,pat = intern_pattern sigma env lfun mp in
+ let lfun',metas1,hyps = intern_match_goal_hyps ist lfun rl in
+ let ido,metas2,pat = intern_pattern ist lfun mp in
let metas = list_uniquize (metas1@metas2) in
let ist' = { ist with ltacvars = (metas@(Option.List.cons ido lfun'),l2) } in
Pat (hyps,pat,intern_tactic ist' tc) :: (intern_match_rule ist tl)
@@ -932,7 +952,7 @@ and intern_genarg ist x =
(intern_intro_pattern lf ist (out_gen rawwit_intro_pattern x))
| IdentArgType b ->
let lf = ref ([],[]) in
- in_gen (globwit_ident_gen b)
+ in_gen (globwit_ident_gen b)
(intern_ident lf ist (out_gen (rawwit_ident_gen b) x))
| VarArgType ->
in_gen globwit_var (intern_hyp ist (out_gen rawwit_var x))
@@ -943,7 +963,7 @@ and intern_genarg ist x =
| ConstrArgType ->
in_gen globwit_constr (intern_constr ist (out_gen rawwit_constr x))
| ConstrMayEvalArgType ->
- in_gen globwit_constr_may_eval
+ in_gen globwit_constr_may_eval
(intern_constr_may_eval ist (out_gen rawwit_constr_may_eval x))
| QuantHypArgType ->
in_gen globwit_quant_hyp
@@ -965,7 +985,7 @@ and intern_genarg ist x =
| PairArgType _ -> app_pair (intern_genarg ist) (intern_genarg ist) x
| ExtraArgType s ->
match tactic_genarg_level s with
- | Some n ->
+ | Some n ->
(* Special treatment of tactic arguments *)
in_gen (globwit_tactic n) (intern_tactic ist
(out_gen (rawwit_tactic n) x))
@@ -977,159 +997,8 @@ and intern_genarg ist x =
(***************************************************************************)
(* Evaluation/interpretation *)
-(* Associates variables with values and gives the remaining variables and
- values *)
-let head_with_value (lvar,lval) =
- let rec head_with_value_rec lacc = function
- | ([],[]) -> (lacc,[],[])
- | (vr::tvr,ve::tve) ->
- (match vr with
- | None -> head_with_value_rec lacc (tvr,tve)
- | Some v -> head_with_value_rec ((v,ve)::lacc) (tvr,tve))
- | (vr,[]) -> (lacc,vr,[])
- | ([],ve) -> (lacc,[],ve)
- in
- head_with_value_rec [] (lvar,lval)
-
-(* Gives a context couple if there is a context identifier *)
-let give_context ctxt = function
- | None -> []
- | Some id -> [id,VConstr_context ctxt]
-
-(* Reads a pattern by substituting vars of lfun *)
-let eval_pattern lfun c =
- let lvar = List.map (fun (id,c) -> (id,lazy(pattern_of_constr c))) lfun in
- instantiate_pattern lvar c
-
-let read_pattern lfun = function
- | Subterm (b,ido,pc) -> Subterm (b,ido,eval_pattern lfun pc)
- | Term pc -> Term (eval_pattern lfun pc)
-
-let value_of_ident id = VIntroPattern (IntroIdentifier id)
-
-let extend_values_with_bindings (ln,lm) lfun =
- let lnames = List.map (fun (id,id') ->(id,value_of_ident id')) ln in
- let lmatch = List.map (fun (id,c) -> (id,VConstr c)) lm in
- (* For compatibility, bound variables are visible only if no other
- binding of the same name exists *)
- lmatch@lfun@lnames
-
-(* Reads the hypotheses of a Match Context rule *)
-let cons_and_check_name id l =
- if List.mem id l then
- user_err_loc (dloc,"read_match_goal_hyps",
- strbrk ("Hypothesis pattern-matching variable "^(string_of_id id)^
- " used twice in the same pattern."))
- else id::l
-
-let rec read_match_goal_hyps lfun lidh = function
- | (Hyp ((loc,na) as locna,mp))::tl ->
- let lidh' = name_fold cons_and_check_name na lidh in
- Hyp (locna,read_pattern lfun mp)::
- (read_match_goal_hyps lfun lidh' tl)
- | (Def ((loc,na) as locna,mv,mp))::tl ->
- let lidh' = name_fold cons_and_check_name na lidh in
- Def (locna,read_pattern lfun mv, read_pattern lfun mp)::
- (read_match_goal_hyps lfun lidh' tl)
- | [] -> []
-
-(* Reads the rules of a Match Context or a Match *)
-let rec read_match_rule lfun = function
- | (All tc)::tl -> (All tc)::(read_match_rule lfun tl)
- | (Pat (rl,mp,tc))::tl ->
- Pat (read_match_goal_hyps lfun [] rl, read_pattern lfun mp,tc)
- :: read_match_rule lfun tl
- | [] -> []
-
-(* For Match Context and Match *)
-exception Not_coherent_metas
-exception Eval_fail of std_ppcmds
-
-let is_match_catchable = function
- | PatternMatchingFailure | Eval_fail _ -> true
- | e -> Logic.catchable_exception e
-
-(* Verifies if the matched list is coherent with respect to lcm *)
-(* While non-linear matching is modulo eq_constr in matches, merge of *)
-(* different instances of the same metavars is here modulo conversion... *)
-let verify_metas_coherence gl (ln1,lcm) (ln,lm) =
- let rec aux = function
- | (num,csr)::tl ->
- if (List.for_all (fun (a,b) -> a<>num or pf_conv_x gl b csr) lcm) then
- (num,csr)::aux tl
- else
- raise Not_coherent_metas
- | [] -> lcm in
- (ln@ln1,aux lm)
-
-(* Tries to match one hypothesis pattern with a list of hypotheses *)
-let apply_one_mhyp_context ist env gl lmatch (hypname,patv,pat) lhyps =
- let get_id_couple id = function
- | Name idpat -> [idpat,VConstr (mkVar id)]
- | Anonymous -> [] in
- let match_pat lmatch hyp pat =
- match pat with
- | Term t ->
- let lmeta = extended_matches t hyp in
- (try
- let lmeta = verify_metas_coherence gl lmatch lmeta in
- ([],lmeta,(fun () -> raise PatternMatchingFailure))
- with
- | Not_coherent_metas -> raise PatternMatchingFailure);
- | Subterm (b,ic,t) ->
- let rec match_next_pattern find_next () =
- let (lmeta,ctxt,find_next') = find_next () in
- try
- let lmeta = verify_metas_coherence gl lmatch lmeta in
- (give_context ctxt ic,lmeta,match_next_pattern find_next')
- with
- | Not_coherent_metas -> match_next_pattern find_next' () in
- match_next_pattern(fun () -> match_subterm_gen b t hyp) () in
- let rec apply_one_mhyp_context_rec = function
- | (id,b,hyp as hd)::tl ->
- (match patv with
- | None ->
- let rec match_next_pattern find_next () =
- try
- let (ids, lmeta, find_next') = find_next () in
- (get_id_couple id hypname@ids, lmeta, hd,
- match_next_pattern find_next')
- with
- | PatternMatchingFailure -> apply_one_mhyp_context_rec tl in
- match_next_pattern (fun () ->
- let hyp = if b<>None then refresh_universes_strict hyp else hyp in
- match_pat lmatch hyp pat) ()
- | Some patv ->
- match b with
- | Some body ->
- let rec match_next_pattern_in_body next_in_body () =
- try
- let (ids,lmeta,next_in_body') = next_in_body() in
- let rec match_next_pattern_in_typ next_in_typ () =
- try
- let (ids',lmeta',next_in_typ') = next_in_typ() in
- (get_id_couple id hypname@ids@ids', lmeta', hd,
- match_next_pattern_in_typ next_in_typ')
- with
- | PatternMatchingFailure ->
- match_next_pattern_in_body next_in_body' () in
- match_next_pattern_in_typ
- (fun () ->
- let hyp = refresh_universes_strict hyp in
- match_pat lmeta hyp pat) ()
- with PatternMatchingFailure -> apply_one_mhyp_context_rec tl
- in
- match_next_pattern_in_body
- (fun () -> match_pat lmatch body patv) ()
- | None -> apply_one_mhyp_context_rec tl)
- | [] ->
- db_hyp_pattern_failure ist.debug env (hypname,pat);
- raise PatternMatchingFailure
- in
- apply_one_mhyp_context_rec lhyps
-
let constr_to_id loc = function
- | VConstr c when isVar c -> destVar c
+ | VConstr ([],c) when isVar c -> destVar c
| _ -> invalid_arg_loc (loc, "Not an identifier")
let constr_to_qid loc c =
@@ -1158,12 +1027,12 @@ let debugging_exception_step ist signal_anomaly e pp =
let explain_exc =
if signal_anomaly then explain_logic_error
else explain_logic_error_no_anomaly in
- debugging_step ist (fun () ->
+ debugging_step ist (fun () ->
pp() ++ spc() ++ str "raised the exception" ++ fnl() ++ !explain_exc e)
let error_ltac_variable loc id env v s =
- user_err_loc (loc, "", str "Ltac variable " ++ pr_id id ++
- strbrk " is bound to" ++ spc () ++ pr_value env v ++ spc () ++
+ user_err_loc (loc, "", str "Ltac variable " ++ pr_id id ++
+ strbrk " is bound to" ++ spc () ++ pr_value env v ++ spc () ++
strbrk "which cannot be coerced to " ++ str s ++ str".")
exception CannotCoerceTo of string
@@ -1180,27 +1049,28 @@ let interp_ltac_var coerce ist env locid =
(* Interprets an identifier which must be fresh *)
let coerce_to_ident fresh env = function
| VIntroPattern (IntroIdentifier id) -> id
- | VConstr c when isVar c & not (fresh & is_variable env (destVar c)) ->
+ | VConstr ([],c) when isVar c & not (fresh & is_variable env (destVar c)) ->
(* We need it fresh for intro e.g. in "Tac H = clear H; intro H" *)
destVar c
| v -> raise (CannotCoerceTo "a fresh identifier")
-let interp_ident_gen fresh ist gl id =
- let env = pf_env gl in
+let interp_ident_gen fresh ist env id =
try try_interp_ltac_var (coerce_to_ident fresh env) ist (Some env) (dloc,id)
with Not_found -> id
-let interp_ident = interp_ident_gen false
+let interp_ident = interp_ident_gen false
let interp_fresh_ident = interp_ident_gen true
+let pf_interp_ident id gl = interp_ident_gen false id (pf_env gl)
+let pf_interp_fresh_ident id gl = interp_ident_gen true id (pf_env gl)
(* Interprets an optional identifier which must be fresh *)
-let interp_fresh_name ist gl = function
+let interp_fresh_name ist env = function
| Anonymous -> Anonymous
- | Name id -> Name (interp_fresh_ident ist gl id)
+ | Name id -> Name (interp_fresh_ident ist env id)
let coerce_to_intro_pattern env = function
| VIntroPattern ipat -> ipat
- | VConstr c when isVar c ->
+ | VConstr ([],c) when isVar c ->
(* This happens e.g. in definitions like "Tac H = clear H; intro H" *)
(* but also in "destruct H as (H,H')" *)
IntroIdentifier (destVar c)
@@ -1237,7 +1107,7 @@ let int_or_var_list_of_VList = function
| _ -> raise Not_found
let interp_int_or_var_as_list ist = function
- | ArgVar (_,id as locid) ->
+ | ArgVar (_,id as locid) ->
(try int_or_var_list_of_VList (List.assoc id ist.lfun)
with Not_found | CannotCoerceTo _ -> [ArgArg (interp_int ist locid)])
| ArgArg n as x -> [x]
@@ -1247,11 +1117,16 @@ let interp_int_or_var_list ist l =
let constr_of_value env = function
| VConstr csr -> csr
- | VIntroPattern (IntroIdentifier id) -> constr_of_id env id
+ | VIntroPattern (IntroIdentifier id) -> ([],constr_of_id env id)
| _ -> raise Not_found
+let closed_constr_of_value env v =
+ let ids,c = constr_of_value env v in
+ if ids <> [] then raise Not_found;
+ c
+
let coerce_to_hyp env = function
- | VConstr c when isVar c -> destVar c
+ | VConstr ([],c) when isVar c -> destVar c
| VIntroPattern (IntroIdentifier id) when is_variable env id -> id
| _ -> raise (CannotCoerceTo "a variable")
@@ -1260,7 +1135,7 @@ let interp_hyp ist gl (loc,id as locid) =
let env = pf_env gl in
(* Look first in lfun for a value coercible to a variable *)
try try_interp_ltac_var (coerce_to_hyp env) ist (Some env) locid
- with Not_found ->
+ with Not_found ->
(* Then look if bound in the proof context at calling time *)
if is_variable env id then id
else user_err_loc (loc,"eval_variable",pr_id id ++ str " not found.")
@@ -1294,19 +1169,19 @@ let interp_move_location ist gl = function
(* Interprets a qualified name *)
let coerce_to_reference env v =
try match v with
- | VConstr c -> global_of_constr c (* may raise Not_found *)
+ | VConstr ([],c) -> global_of_constr c (* may raise Not_found *)
| _ -> raise Not_found
with Not_found -> raise (CannotCoerceTo "a reference")
let interp_reference ist env = function
| ArgArg (_,r) -> r
- | ArgVar locid ->
+ | ArgVar locid ->
interp_ltac_var (coerce_to_reference env) ist (Some env) locid
let pf_interp_reference ist gl = interp_reference ist (pf_env gl)
let coerce_to_inductive = function
- | VConstr c when isInd c -> destInd c
+ | VConstr ([],c) when isInd c -> destInd c
| _ -> raise (CannotCoerceTo "an inductive type")
let interp_inductive ist = function
@@ -1315,9 +1190,9 @@ let interp_inductive ist = function
let coerce_to_evaluable_ref env v =
let ev = match v with
- | VConstr c when isConst c -> EvalConstRef (destConst c)
- | VConstr c when isVar c -> EvalVarRef (destVar c)
- | VIntroPattern (IntroIdentifier id) when List.mem id (ids_of_context env)
+ | VConstr ([],c) when isConst c -> EvalConstRef (destConst c)
+ | VConstr ([],c) when isVar c -> EvalVarRef (destVar c)
+ | VIntroPattern (IntroIdentifier id) when List.mem id (ids_of_context env)
-> EvalVarRef id
| _ -> raise (CannotCoerceTo "an evaluable reference")
in
@@ -1331,13 +1206,13 @@ let interp_evaluable ist env = function
(* Maybe [id] has been introduced by Intro-like tactics *)
(try match Environ.lookup_named id env with
| (_,Some _,_) -> EvalVarRef id
- | _ -> error_not_evaluable (pr_id id)
+ | _ -> error_not_evaluable (VarRef id)
with Not_found ->
match r with
| EvalConstRef _ -> r
| _ -> Pretype_errors.error_var_not_found_loc loc id)
| ArgArg (r,None) -> r
- | ArgVar locid ->
+ | ArgVar locid ->
interp_ltac_var (coerce_to_evaluable_ref env) ist (Some env) locid
(* Interprets an hypothesis name *)
@@ -1354,25 +1229,26 @@ let interp_clause ist gl { onhyps=ol; concl_occs=occs } =
(* Interpretation of constructions *)
(* Extract the constr list from lfun *)
-let rec constr_list_aux env = function
- | (id,v)::tl ->
- let (l1,l2) = constr_list_aux env tl in
+let extract_ltac_constr_values ist env =
+ let rec aux = function
+ | (id,v)::tl ->
+ let (l1,l2) = aux tl in
(try ((id,constr_of_value env v)::l1,l2)
- with Not_found ->
+ with Not_found ->
let ido = match v with
| VIntroPattern (IntroIdentifier id0) -> Some id0
| _ -> None in
(l1,(id,ido)::l2))
- | [] -> ([],[])
-
-let constr_list ist env = constr_list_aux env ist.lfun
+ | [] -> ([],[]) in
+ aux ist.lfun
(* Extract the identifier list from lfun: join all branches (what to do else?)*)
let rec intropattern_ids (loc,pat) = match pat with
| IntroIdentifier id -> [id]
- | IntroOrAndPattern ll ->
+ | IntroOrAndPattern ll ->
List.flatten (List.map intropattern_ids (List.flatten ll))
- | IntroWildcard | IntroAnonymous | IntroFresh _ | IntroRewrite _ -> []
+ | IntroWildcard | IntroAnonymous | IntroFresh _ | IntroRewrite _
+ | IntroForthcoming _ -> []
let rec extract_ids ids = function
| (id,VIntroPattern ipat)::tl when not (List.mem id ids) ->
@@ -1382,33 +1258,21 @@ let rec extract_ids ids = function
let default_fresh_id = id_of_string "H"
-let interp_fresh_id ist gl l =
+let interp_fresh_id ist env l =
let ids = map_succeed (function ArgVar(_,id) -> id | _ -> failwith "") l in
let avoid = (extract_ids ids ist.lfun) @ ist.avoid_ids in
- let id =
- if l = [] then default_fresh_id
+ let id =
+ if l = [] then default_fresh_id
else
let s =
String.concat "" (List.map (function
| ArgArg s -> s
- | ArgVar (_,id) -> string_of_id (interp_ident ist gl id)) l) in
+ | ArgVar (_,id) -> string_of_id (interp_ident ist env id)) l) in
let s = if Lexer.is_keyword s then s^"0" else s in
id_of_string s in
- Tactics.fresh_id avoid id gl
-
-(* To retype a list of key*constr with undefined key *)
-let retype_list sigma env lst =
- List.fold_right (fun (x,csr) a ->
- try (x,Retyping.get_judgment_of env sigma csr)::a with
- | Anomaly _ -> a) lst []
+ Tactics.fresh_id_in_env avoid id env
-let extract_ltac_vars_data ist sigma env =
- let (ltacvars,_ as vars) = constr_list ist env in
- vars, retype_list sigma env ltacvars
-
-let extract_ltac_vars ist sigma env =
- let (_,unbndltacvars),typs = extract_ltac_vars_data ist sigma env in
- typs,unbndltacvars
+let pf_interp_fresh_id ist gl = interp_fresh_id ist (pf_env gl)
let implicit_tactic = ref None
@@ -1416,11 +1280,11 @@ let declare_implicit_tactic tac = implicit_tactic := Some tac
open Evd
-let solvable_by_tactic env evi (ev,args) src =
+let solvable_by_tactic env evi (ev,args) src =
match (!implicit_tactic, src) with
| Some tac, (ImplicitArg _ | QuestionMark _)
- when
- Environ.named_context_of_val evi.evar_hyps =
+ when
+ Environ.named_context_of_val evi.evar_hyps =
Environ.named_context env ->
let id = id_of_string "H" in
start_proof id (Local,Proof Lemma) evi.evar_hyps evi.evar_concl
@@ -1428,35 +1292,42 @@ let solvable_by_tactic env evi (ev,args) src =
begin
try
by (tclCOMPLETE tac);
- let _,(const,_,_,_) = cook_proof ignore in
+ let _,(const,_,_,_) = cook_proof ignore in
delete_current_proof (); const.const_entry_body
- with e when Logic.catchable_exception e ->
+ with e when Logic.catchable_exception e ->
delete_current_proof();
raise Exit
end
| _ -> raise Exit
-let solve_remaining_evars env initial_sigma evd c =
- let evdref = ref (Typeclasses.resolve_typeclasses ~fail:true env evd) in
+let solve_remaining_evars fail_evar use_classes env initial_sigma evd c =
+ let evdref =
+ if use_classes then ref (Typeclasses.resolve_typeclasses ~fail:true env evd)
+ else ref evd in
let rec proc_rec c =
- match kind_of_term (Reductionops.whd_evar (evars_of !evdref) c) with
+ let c = Reductionops.whd_evar !evdref c in
+ match kind_of_term c with
| Evar (ev,args as k) when not (Evd.mem initial_sigma ev) ->
let (loc,src) = evar_source ev !evdref in
- let sigma = evars_of !evdref in
+ let sigma = !evdref in
let evi = Evd.find sigma ev in
- (try
+ (try
let c = solvable_by_tactic env evi k src in
- evdref := Evd.evar_define ev c !evdref;
+ evdref := Evd.define ev c !evdref;
c
with Exit ->
- Pretype_errors.error_unsolvable_implicit loc env sigma evi src None)
- | _ -> map_constr proc_rec c
+ if fail_evar then
+ Pretype_errors.error_unsolvable_implicit loc env sigma evi src None
+ else
+ c)
+ | _ -> map_constr proc_rec c
in
- proc_rec (Evarutil.nf_isevar !evdref c)
+ let c = proc_rec c in
+ (* Side-effect *)
+ !evdref,c
-let interp_gen kind ist sigma env (c,ce) =
- let (ltacvars,unbndltacvars as vars),typs =
- extract_ltac_vars_data ist sigma env in
+let interp_gen kind ist allow_patvar expand_evar fail_evar use_classes env sigma (c,ce) =
+ let (ltacvars,unbndltacvars as vars) = extract_ltac_constr_values ist env in
let c = match ce with
| None -> c
(* If at toplevel (ce<>None), the error can be due to an incorrect
@@ -1464,100 +1335,78 @@ let interp_gen kind ist sigma env (c,ce) =
intros/lettac/inversion hypothesis names *)
| Some c ->
let ltacdata = (List.map fst ltacvars,unbndltacvars) in
- intern_gen (kind = IsType) ~ltacvars:ltacdata sigma env c in
- let trace = (dloc,LtacConstrInterp (c,vars))::ist.trace in
- catch_error trace (understand_ltac sigma env (typs,unbndltacvars) kind) c
+ intern_gen (kind = IsType) ~allow_patvar ~ltacvars:ltacdata sigma env c
+ in
+ let trace = push_trace (dloc,LtacConstrInterp (c,vars)) ist.trace in
+ let evd,c =
+ catch_error trace (understand_ltac expand_evar sigma env vars kind) c in
+ let evd,c =
+ if expand_evar then
+ solve_remaining_evars fail_evar use_classes env sigma evd c
+ else
+ evd,c in
+ db_constr ist.debug env c;
+ (evd,c)
-(* Interprets a constr and solve remaining evars with default tactic *)
-let interp_econstr kind ist sigma env cc =
- let evars,c = interp_gen kind ist sigma env cc in
- let csr = solve_remaining_evars env sigma evars c in
- db_constr ist.debug env csr;
- csr
+(* Interprets a constr; expects evars to be solved *)
+let interp_constr_gen kind ist env sigma c =
+ snd (interp_gen kind ist false true true true env sigma c)
-(* Interprets an open constr *)
-let interp_open_constr ccl ist sigma env cc =
- let evd,c = interp_gen (OfType ccl) ist sigma env cc in
- (evars_of evd,c)
+let interp_constr = interp_constr_gen (OfType None)
+
+let interp_type = interp_constr_gen IsType
-let interp_open_type ccl ist sigma env cc =
- let evd,c = interp_gen IsType ist sigma env cc in
- (evars_of evd,c)
+(* Interprets an open constr *)
+let interp_open_constr_gen kind ist =
+ interp_gen kind ist false true false false
-let interp_constr = interp_econstr (OfType None)
+let interp_open_constr ccl =
+ interp_open_constr_gen (OfType ccl)
-let interp_type = interp_econstr IsType
+let interp_typed_pattern ist env sigma (c,_) =
+ let sigma, c =
+ interp_gen (OfType None) ist true false false false env sigma c in
+ pattern_of_constr sigma c
(* Interprets a constr expression casted by the current goal *)
-let pf_interp_casted_constr ist gl cc =
- interp_econstr (OfType (Some (pf_concl gl))) ist (project gl) (pf_env gl) cc
-
-(* Interprets an open constr expression *)
-let pf_interp_open_constr casted ist gl cc =
- let cl = if casted then Some (pf_concl gl) else None in
- interp_open_constr cl ist (project gl) (pf_env gl) cc
+let pf_interp_casted_constr ist gl c =
+ interp_constr_gen (OfType (Some (pf_concl gl))) ist (pf_env gl) (project gl) c
(* Interprets a constr expression *)
let pf_interp_constr ist gl =
- interp_constr ist (project gl) (pf_env gl)
+ interp_constr ist (pf_env gl) (project gl)
let constr_list_of_VList env = function
- | VList l -> List.map (constr_of_value env) l
+ | VList l -> List.map (closed_constr_of_value env) l
| _ -> raise Not_found
-let pf_interp_constr_in_compound_list inj_fun dest_fun interp_fun ist gl l =
- let env = pf_env gl in
- let try_expand_ltac_var x =
+let interp_constr_in_compound_list inj_fun dest_fun interp_fun ist env sigma l =
+ let try_expand_ltac_var sigma x =
try match dest_fun x with
- | RVar (_,id), _ ->
- List.map inj_fun (constr_list_of_VList env (List.assoc id ist.lfun))
+ | RVar (_,id), _ ->
+ sigma,
+ List.map inj_fun (constr_list_of_VList env (List.assoc id ist.lfun))
| _ ->
- raise Not_found
+ raise Not_found
with Not_found ->
(*all of dest_fun, List.assoc, constr_list_of_VList may raise Not_found*)
- [interp_fun ist gl x] in
- List.flatten (List.map try_expand_ltac_var l)
+ let sigma, c = interp_fun ist env sigma x in
+ sigma, [c] in
+ let sigma, l = list_fold_map try_expand_ltac_var sigma l in
+ sigma, List.flatten l
-let pf_interp_constr_list =
- pf_interp_constr_in_compound_list (fun x -> x) (fun x -> x)
- (fun ist gl -> interp_constr ist (project gl) (pf_env gl))
-
-(*
-let pf_interp_constr_list_as_list ist gl (c,_ as x) =
- match c with
- | RVar (_,id) ->
- (try constr_list_of_VList (pf_env gl) (List.assoc id ist.lfun)
- with Not_found -> [])
- | _ -> [interp_constr ist (project gl) (pf_env gl) x]
-
-let pf_interp_constr_list ist gl l =
- List.flatten (List.map (pf_interp_constr_list_as_list ist gl) l)
-*)
+let interp_constr_list ist env sigma c =
+ snd (interp_constr_in_compound_list (fun x -> x) (fun x -> x) (fun ist env sigma c -> (Evd.empty, interp_constr ist env sigma c)) ist env sigma c)
let inj_open c = (Evd.empty,c)
-let pf_interp_open_constr_list =
- pf_interp_constr_in_compound_list inj_open (fun x -> x)
- (fun ist gl -> interp_open_constr None ist (project gl) (pf_env gl))
-
-(*
-let pf_interp_open_constr_list_as_list ist gl (c,_ as x) =
- match c with
- | RVar (_,id) ->
- (try List.map inj_open
- (constr_list_of_VList (pf_env gl) (List.assoc id ist.lfun))
- with Not_found ->
- [interp_open_constr None ist (project gl) (pf_env gl) x])
- | _ ->
- [interp_open_constr None ist (project gl) (pf_env gl) x]
-
-let pf_interp_open_constr_list ist gl l =
- List.flatten (List.map (pf_interp_open_constr_list_as_list ist gl) l)
-*)
+let interp_open_constr_list =
+ interp_constr_in_compound_list (fun x -> x) (fun x -> x)
+ (interp_open_constr None)
(* Interprets a type expression *)
let pf_interp_type ist gl =
- interp_type ist (project gl) (pf_env gl)
+ interp_type ist (pf_env gl) (project gl)
(* Interprets a reduction expression *)
let interp_unfold ist env (occs,qid) =
@@ -1566,28 +1415,34 @@ let interp_unfold ist env (occs,qid) =
let interp_flag ist env red =
{ red with rConst = List.map (interp_evaluable ist env) red.rConst }
-let interp_pattern ist sigma env (occs,c) =
+let interp_constr_with_occurrences ist sigma env (occs,c) =
(interp_occurrences ist occs, interp_constr ist sigma env c)
-let pf_interp_constr_with_occurrences ist gl =
- interp_pattern ist (project gl) (pf_env gl)
+let interp_typed_pattern_with_occurrences ist env sigma (occs,c) =
+ let sign,p = interp_typed_pattern ist env sigma c in
+ sign, (interp_occurrences ist occs, p)
-let pf_interp_constr_with_occurrences_and_name_as_list =
- pf_interp_constr_in_compound_list
+let interp_closed_typed_pattern_with_occurrences ist env sigma occl =
+ snd (interp_typed_pattern_with_occurrences ist env sigma occl)
+
+let interp_constr_with_occurrences_and_name_as_list =
+ interp_constr_in_compound_list
(fun c -> ((all_occurrences_expr,c),Anonymous))
- (function ((occs,c),Anonymous) when occs = all_occurrences_expr -> c
+ (function ((occs,c),Anonymous) when occs = all_occurrences_expr -> c
| _ -> raise Not_found)
- (fun ist gl (occ_c,na) ->
- (interp_pattern ist (project gl) (pf_env gl) occ_c,
- interp_fresh_name ist gl na))
+ (fun ist env sigma (occ_c,na) ->
+ sigma, (interp_constr_with_occurrences ist env sigma occ_c,
+ interp_fresh_name ist env na))
let interp_red_expr ist sigma env = function
| Unfold l -> Unfold (List.map (interp_unfold ist env) l)
- | Fold l -> Fold (List.map (interp_constr ist sigma env) l)
+ | Fold l -> Fold (List.map (interp_constr ist env sigma) l)
| Cbv f -> Cbv (interp_flag ist env f)
| Lazy f -> Lazy (interp_flag ist env f)
- | Pattern l -> Pattern (List.map (interp_pattern ist sigma env) l)
- | Simpl o -> Simpl (Option.map (interp_pattern ist sigma env) o)
+ | Pattern l ->
+ Pattern (List.map (interp_constr_with_occurrences ist env sigma) l)
+ | Simpl o ->
+ Simpl(Option.map (interp_closed_typed_pattern_with_occurrences ist env sigma) o)
| (Red _ | Hnf | ExtraRedExpr _ | CbvVm as r) -> r
let pf_interp_red_expr ist gl = interp_red_expr ist (project gl) (pf_env gl)
@@ -1606,17 +1461,17 @@ let interp_may_eval f ist gl = function
user_err_loc (loc, "interp_may_eval",
str "Unbound context identifier" ++ pr_id s ++ str"."))
| ConstrTypeOf c -> pf_type_of gl (f ist gl c)
- | ConstrTerm c ->
- try
+ | ConstrTerm c ->
+ try
f ist gl c
with e ->
debugging_exception_step ist false e (fun () ->
str"interpretation of term " ++ pr_rawconstr_env (pf_env gl) (fst c));
- raise e
+ raise e
(* Interprets a constr expression possibly to first evaluate *)
let interp_constr_may_eval ist gl c =
- let csr =
+ let csr =
try
interp_may_eval pf_interp_constr ist gl c
with e ->
@@ -1628,48 +1483,56 @@ let interp_constr_may_eval ist gl c =
csr
end
-let inj_may_eval = function
- | ConstrTerm c -> ConstrTerm (inj_open c)
- | ConstrEval (r,c) -> ConstrEval (Tactics.inj_red_expr r,inj_open c)
- | ConstrContext (id,c) -> ConstrContext (id,inj_open c)
- | ConstrTypeOf c -> ConstrTypeOf (inj_open c)
-
-let message_of_value = function
+let rec message_of_value gl = function
| VVoid -> str "()"
| VInteger n -> int n
| VIntroPattern ipat -> pr_intro_pattern (dloc,ipat)
- | VConstr_context c | VConstr c -> pr_constr c
+ | VConstr_context c -> pr_constr_env (pf_env gl) c
+ | VConstr c -> pr_constr_under_binders_env (pf_env gl) c
| VRec _ | VRTactic _ | VFun _ -> str "<tactic>"
- | VList _ -> str "<list>"
+ | VList l -> prlist_with_sep spc (message_of_value gl) l
-let rec interp_message_token ist = function
+let rec interp_message_token ist gl = function
| MsgString s -> str s
| MsgInt n -> int n
| MsgIdent (loc,id) ->
let v =
try List.assoc id ist.lfun
with Not_found -> user_err_loc (loc,"",pr_id id ++ str" not found.") in
- message_of_value v
+ message_of_value gl v
-let rec interp_message_nl ist = function
+let rec interp_message_nl ist gl = function
| [] -> mt()
- | l -> prlist_with_sep spc (interp_message_token ist) l ++ fnl()
+ | l -> prlist_with_sep spc (interp_message_token ist gl) l ++ fnl()
-let interp_message ist l =
- (* Force evaluation of interp_message_token so that potential errors
+let interp_message ist gl l =
+ (* Force evaluation of interp_message_token so that potential errors
are raised now and not at printing time *)
- prlist (fun x -> spc () ++ x) (List.map (interp_message_token ist) l)
+ prlist (fun x -> spc () ++ x) (List.map (interp_message_token ist gl) l)
+
+let intro_pattern_list_of_Vlist loc env = function
+ | VList l -> List.map (fun a -> loc,coerce_to_intro_pattern env a) l
+ | _ -> raise Not_found
let rec interp_intro_pattern ist gl = function
| loc, IntroOrAndPattern l ->
loc, IntroOrAndPattern (interp_or_and_intro_pattern ist gl l)
| loc, IntroIdentifier id ->
loc, interp_intro_pattern_var loc ist (pf_env gl) id
- | loc, (IntroWildcard | IntroAnonymous | IntroFresh _ | IntroRewrite _)
+ | loc, IntroFresh id ->
+ loc, IntroFresh (interp_fresh_ident ist (pf_env gl) id)
+ | loc, (IntroWildcard | IntroAnonymous | IntroRewrite _ | IntroForthcoming _)
as x -> x
and interp_or_and_intro_pattern ist gl =
- List.map (List.map (interp_intro_pattern ist gl))
+ List.map (interp_intro_pattern_list_as_list ist gl)
+
+and interp_intro_pattern_list_as_list ist gl = function
+ | [loc,IntroIdentifier id] as l ->
+ (try intro_pattern_list_of_Vlist loc (pf_env gl) (List.assoc id ist.lfun)
+ with Not_found | CannotCoerceTo _ ->
+ List.map (interp_intro_pattern ist gl) l)
+ | l -> List.map (interp_intro_pattern ist gl) l
let interp_in_hyp_as ist gl (id,ipat) =
(interp_hyp ist gl id,Option.map (interp_intro_pattern ist gl) ipat)
@@ -1700,56 +1563,249 @@ let interp_binding_name ist = function
(* (as in Inversion) *)
let coerce_to_decl_or_quant_hyp env = function
| VInteger n -> AnonHyp n
- | v ->
+ | v ->
try NamedHyp (coerce_to_hyp env v)
- with CannotCoerceTo _ ->
+ with CannotCoerceTo _ ->
raise (CannotCoerceTo "a declared or quantified hypothesis")
let interp_declared_or_quantified_hypothesis ist gl = function
| AnonHyp n -> AnonHyp n
| NamedHyp id ->
let env = pf_env gl in
- try try_interp_ltac_var
+ try try_interp_ltac_var
(coerce_to_decl_or_quant_hyp env) ist (Some env) (dloc,id)
with Not_found -> NamedHyp id
-let interp_binding ist gl (loc,b,c) =
- (loc,interp_binding_name ist b,pf_interp_open_constr false ist gl c)
-
-let interp_bindings ist gl = function
-| NoBindings -> NoBindings
-| ImplicitBindings l -> ImplicitBindings (pf_interp_open_constr_list ist gl l)
-| ExplicitBindings l -> ExplicitBindings (List.map (interp_binding ist gl) l)
-
-let interp_constr_with_bindings ist gl (c,bl) =
- (pf_interp_constr ist gl c, interp_bindings ist gl bl)
-
-let interp_open_constr_with_bindings ist gl (c,bl) =
- (pf_interp_open_constr false ist gl c, interp_bindings ist gl bl)
-
-let interp_induction_arg ist gl = function
- | ElimOnConstr c -> ElimOnConstr (interp_constr_with_bindings ist gl c)
- | ElimOnAnonHyp n as x -> x
+let interp_binding ist env sigma (loc,b,c) =
+ let sigma, c = interp_open_constr None ist env sigma c in
+ sigma, (loc,interp_binding_name ist b,c)
+
+let interp_bindings ist env sigma = function
+| NoBindings ->
+ sigma, NoBindings
+| ImplicitBindings l ->
+ let sigma, l = interp_open_constr_list ist env sigma l in
+ sigma, ImplicitBindings l
+| ExplicitBindings l ->
+ let sigma, l = list_fold_map (interp_binding ist env) sigma l in
+ sigma, ExplicitBindings l
+
+let interp_constr_with_bindings ist env sigma (c,bl) =
+ let sigma, bl = interp_bindings ist env sigma bl in
+ let sigma, c = interp_open_constr None ist env sigma c in
+ sigma, (c,bl)
+
+let interp_open_constr_with_bindings ist env sigma (c,bl) =
+ let sigma, bl = interp_bindings ist env sigma bl in
+ let sigma, c = interp_open_constr None ist env sigma c in
+ sigma, (c, bl)
+
+let loc_of_bindings = function
+| NoBindings -> dummy_loc
+| ImplicitBindings l -> loc_of_rawconstr (fst (list_last l))
+| ExplicitBindings l -> pi1 (list_last l)
+
+let interp_open_constr_with_bindings_loc ist env sigma ((c,_),bl as cb) =
+ let loc1 = loc_of_rawconstr c in
+ let loc2 = loc_of_bindings bl in
+ let loc = if loc2 = dummy_loc then loc1 else join_loc loc1 loc2 in
+ let sigma, cb = interp_open_constr_with_bindings ist env sigma cb in
+ sigma, (loc,cb)
+
+let interp_induction_arg ist gl sigma arg =
+ let env = pf_env gl in
+ match arg with
+ | ElimOnConstr c ->
+ let sigma, c = interp_constr_with_bindings ist env sigma c in
+ sigma, ElimOnConstr c
+ | ElimOnAnonHyp n as x -> sigma, x
| ElimOnIdent (loc,id) ->
try
- match List.assoc id ist.lfun with
+ sigma,
+ match List.assoc id ist.lfun with
| VInteger n -> ElimOnAnonHyp n
| VIntroPattern (IntroIdentifier id) -> ElimOnIdent (loc,id)
- | VConstr c -> ElimOnConstr (c,NoBindings)
+ | VConstr ([],c) -> ElimOnConstr (c,NoBindings)
| _ -> user_err_loc (loc,"",
strbrk "Cannot coerce " ++ pr_id id ++
strbrk " neither to a quantified hypothesis nor to a term.")
with Not_found ->
(* Interactive mode *)
- if Tactics.is_quantified_hypothesis id gl then ElimOnIdent (loc,id)
- else ElimOnConstr
- (pf_interp_constr ist gl (RVar (loc,id),Some (CRef (Ident (loc,id)))),
- NoBindings)
+ if Tactics.is_quantified_hypothesis id gl then
+ sigma, ElimOnIdent (loc,id)
+ else
+ let c = interp_constr ist env sigma (RVar (loc,id),Some (CRef (Ident (loc,id)))) in
+ sigma, ElimOnConstr (c,NoBindings)
+
+(* Associates variables with values and gives the remaining variables and
+ values *)
+let head_with_value (lvar,lval) =
+ let rec head_with_value_rec lacc = function
+ | ([],[]) -> (lacc,[],[])
+ | (vr::tvr,ve::tve) ->
+ (match vr with
+ | None -> head_with_value_rec lacc (tvr,tve)
+ | Some v -> head_with_value_rec ((v,ve)::lacc) (tvr,tve))
+ | (vr,[]) -> (lacc,vr,[])
+ | ([],ve) -> (lacc,[],ve)
+ in
+ head_with_value_rec [] (lvar,lval)
+
+(* Gives a context couple if there is a context identifier *)
+let give_context ctxt = function
+ | None -> []
+ | Some id -> [id,VConstr_context ctxt]
+
+(* Reads a pattern by substituting vars of lfun *)
+let use_types = false
-let mk_constr_value ist gl c = VConstr (pf_interp_constr ist gl c)
-let mk_hyp_value ist gl c = VConstr (mkVar (interp_hyp ist gl c))
+let eval_pattern lfun ist env sigma (_,pat as c) =
+ if use_types then
+ snd (interp_typed_pattern ist env sigma c)
+ else
+ instantiate_pattern sigma lfun pat
+
+let read_pattern lfun ist env sigma = function
+ | Subterm (b,ido,c) -> Subterm (b,ido,eval_pattern lfun ist env sigma c)
+ | Term c -> Term (eval_pattern lfun ist env sigma c)
+
+(* Reads the hypotheses of a Match Context rule *)
+let cons_and_check_name id l =
+ if List.mem id l then
+ user_err_loc (dloc,"read_match_goal_hyps",
+ strbrk ("Hypothesis pattern-matching variable "^(string_of_id id)^
+ " used twice in the same pattern."))
+ else id::l
+
+let rec read_match_goal_hyps lfun ist env sigma lidh = function
+ | (Hyp ((loc,na) as locna,mp))::tl ->
+ let lidh' = name_fold cons_and_check_name na lidh in
+ Hyp (locna,read_pattern lfun ist env sigma mp)::
+ (read_match_goal_hyps lfun ist env sigma lidh' tl)
+ | (Def ((loc,na) as locna,mv,mp))::tl ->
+ let lidh' = name_fold cons_and_check_name na lidh in
+ Def (locna,read_pattern lfun ist env sigma mv, read_pattern lfun ist env sigma mp)::
+ (read_match_goal_hyps lfun ist env sigma lidh' tl)
+ | [] -> []
+
+(* Reads the rules of a Match Context or a Match *)
+let rec read_match_rule lfun ist env sigma = function
+ | (All tc)::tl -> (All tc)::(read_match_rule lfun ist env sigma tl)
+ | (Pat (rl,mp,tc))::tl ->
+ Pat (read_match_goal_hyps lfun ist env sigma [] rl, read_pattern lfun ist env sigma mp,tc)
+ :: read_match_rule lfun ist env sigma tl
+ | [] -> []
+
+(* For Match Context and Match *)
+exception Not_coherent_metas
+exception Eval_fail of std_ppcmds
+
+let is_match_catchable = function
+ | PatternMatchingFailure | Eval_fail _ -> true
+ | e -> Logic.catchable_exception e
+
+let equal_instances gl (ctx',c') (ctx,c) =
+ (* How to compare instances? Do we want the terms to be convertible?
+ unifiable? Do we want the universe levels to be relevant?
+ (historically, conv_x is used) *)
+ ctx = ctx' & pf_conv_x gl c' c
+
+(* Verifies if the matched list is coherent with respect to lcm *)
+(* While non-linear matching is modulo eq_constr in matches, merge of *)
+(* different instances of the same metavars is here modulo conversion... *)
+let verify_metas_coherence gl (ln1,lcm) (ln,lm) =
+ let rec aux = function
+ | (id,c as x)::tl ->
+ if List.for_all (fun (id',c') -> id'<>id or equal_instances gl c' c) lcm
+ then
+ x :: aux tl
+ else
+ raise Not_coherent_metas
+ | [] -> lcm in
+ (ln@ln1,aux lm)
+
+let adjust (l,lc) = (l,List.map (fun (id,c) -> (id,([],c))) lc)
+
+(* Tries to match one hypothesis pattern with a list of hypotheses *)
+let apply_one_mhyp_context ist env gl lmatch (hypname,patv,pat) lhyps =
+ let get_id_couple id = function
+ | Name idpat -> [idpat,VConstr ([],mkVar id)]
+ | Anonymous -> [] in
+ let match_pat lmatch hyp pat =
+ match pat with
+ | Term t ->
+ let lmeta = extended_matches t hyp in
+ (try
+ let lmeta = verify_metas_coherence gl lmatch lmeta in
+ ([],lmeta,(fun () -> raise PatternMatchingFailure))
+ with
+ | Not_coherent_metas -> raise PatternMatchingFailure);
+ | Subterm (b,ic,t) ->
+ let rec match_next_pattern find_next () =
+ let (lmeta,ctxt,find_next') = find_next () in
+ try
+ let lmeta = verify_metas_coherence gl lmatch (adjust lmeta) in
+ (give_context ctxt ic,lmeta,match_next_pattern find_next')
+ with
+ | Not_coherent_metas -> match_next_pattern find_next' () in
+ match_next_pattern (fun () -> match_subterm_gen b t hyp) () in
+ let rec apply_one_mhyp_context_rec = function
+ | (id,b,hyp as hd)::tl ->
+ (match patv with
+ | None ->
+ let rec match_next_pattern find_next () =
+ try
+ let (ids, lmeta, find_next') = find_next () in
+ (get_id_couple id hypname@ids, lmeta, hd,
+ match_next_pattern find_next')
+ with
+ | PatternMatchingFailure -> apply_one_mhyp_context_rec tl in
+ match_next_pattern (fun () ->
+ let hyp = if b<>None then refresh_universes_strict hyp else hyp in
+ match_pat lmatch hyp pat) ()
+ | Some patv ->
+ match b with
+ | Some body ->
+ let rec match_next_pattern_in_body next_in_body () =
+ try
+ let (ids,lmeta,next_in_body') = next_in_body() in
+ let rec match_next_pattern_in_typ next_in_typ () =
+ try
+ let (ids',lmeta',next_in_typ') = next_in_typ() in
+ (get_id_couple id hypname@ids@ids', lmeta', hd,
+ match_next_pattern_in_typ next_in_typ')
+ with
+ | PatternMatchingFailure ->
+ match_next_pattern_in_body next_in_body' () in
+ match_next_pattern_in_typ
+ (fun () ->
+ let hyp = refresh_universes_strict hyp in
+ match_pat lmeta hyp pat) ()
+ with PatternMatchingFailure -> apply_one_mhyp_context_rec tl
+ in
+ match_next_pattern_in_body
+ (fun () -> match_pat lmatch body patv) ()
+ | None -> apply_one_mhyp_context_rec tl)
+ | [] ->
+ db_hyp_pattern_failure ist.debug env (hypname,pat);
+ raise PatternMatchingFailure
+ in
+ apply_one_mhyp_context_rec lhyps
+
+(* misc *)
+
+let mk_constr_value ist gl c = VConstr ([],pf_interp_constr ist gl c)
+let mk_hyp_value ist gl c = VConstr ([],mkVar (interp_hyp ist gl c))
let mk_int_or_var_value ist c = VInteger (interp_int_or_var ist c)
+let pack_sigma (sigma,c) = {it=c;sigma=sigma}
+
+let extend_gl_hyps gl sign =
+ { gl with
+ it = { gl.it with
+ evar_hyps =
+ List.fold_right Environ.push_named_context_val sign gl.it.evar_hyps } }
+
(* Interprets an l-tac expression into a value *)
let rec val_interp ist gl (tac:glob_tactic_expr) =
@@ -1758,13 +1814,13 @@ let rec val_interp ist gl (tac:glob_tactic_expr) =
| TacFun (it,body) -> VFun (ist.trace,ist.lfun,it,body)
| TacLetIn (true,l,u) -> interp_letrec ist gl l u
| TacLetIn (false,l,u) -> interp_letin ist gl l u
- | TacMatchGoal (lz,lr,lmr) -> interp_match_goal ist gl lz lr lmr
+ | TacMatchGoal (lz,lr,lmr) -> interp_match_goal ist gl lz lr lmr
| TacMatch (lz,c,lmr) -> interp_match ist gl lz c lmr
| TacArg a -> interp_tacarg ist gl a
(* Delayed evaluation *)
| t -> VFun (ist.trace,ist.lfun,[],t)
- in check_for_interrupt ();
+ in check_for_interrupt ();
match ist.debug with
| DebugOn lev ->
debug_prompt lev gl tac (fun v -> value_interp {ist with debug=v})
@@ -1776,26 +1832,27 @@ and eval_tactic ist = function
let box = ref None in abstract_tactic_box := box;
let call = LtacAtomCall (t,box) in
let tac = (* catch error in the interpretation *)
- catch_error ((dloc,call)::ist.trace) (interp_atomic ist gl) t in
+ catch_error (push_trace(dloc,call)ist.trace)
+ (interp_atomic ist gl) t in
(* catch error in the evaluation *)
- catch_error ((loc,call)::ist.trace) tac gl
+ catch_error (push_trace(loc,call)ist.trace) tac gl
| TacFun _ | TacLetIn _ -> assert false
| TacMatchGoal _ | TacMatch _ -> assert false
- | TacId s -> tclIDTAC_MESSAGE (interp_message_nl ist s)
- | TacFail (n,s) -> tclFAIL (interp_int_or_var ist n) (interp_message ist s)
+ | TacId s -> fun gl -> tclIDTAC_MESSAGE (interp_message_nl ist gl s) gl
+ | TacFail (n,s) -> fun gl -> tclFAIL (interp_int_or_var ist n) (interp_message ist gl s) gl
| TacProgress tac -> tclPROGRESS (interp_tactic ist tac)
| TacAbstract (tac,ido) ->
fun gl -> Tactics.tclABSTRACT
- (Option.map (interp_ident ist gl) ido) (interp_tactic ist tac) gl
- | TacThen (t1,tf,t,tl) ->
+ (Option.map (pf_interp_ident ist gl) ido) (interp_tactic ist tac) gl
+ | TacThen (t1,tf,t,tl) ->
tclTHENS3PARTS (interp_tactic ist t1)
(Array.map (interp_tactic ist) tf) (interp_tactic ist t) (Array.map (interp_tactic ist) tl)
| TacThens (t1,tl) -> tclTHENS (interp_tactic ist t1) (List.map (interp_tactic ist) tl)
| TacDo (n,tac) -> tclDO (interp_int_or_var ist n) (interp_tactic ist tac)
| TacTry tac -> tclTRY (interp_tactic ist tac)
- | TacInfo tac ->
+ | TacInfo tac ->
let t = (interp_tactic ist tac) in
- tclINFO
+ tclINFO
begin
match tac with
TacAtom (_,_) -> t
@@ -1807,7 +1864,7 @@ and eval_tactic ist = function
| TacFirst l -> tclFIRST (List.map (interp_tactic ist) l)
| TacSolve l -> tclSOLVE (List.map (interp_tactic ist) l)
| TacComplete tac -> tclCOMPLETE (interp_tactic ist tac)
- | TacArg a -> assert false
+ | TacArg a -> interp_tactic ist (TacArg a)
and force_vrec ist gl = function
| VRec (lfun,body) -> val_interp {ist with lfun = !lfun} gl body
@@ -1822,9 +1879,9 @@ and interp_ltac_reference loc' mustbetac ist gl = function
| ArgArg (loc,r) ->
let ids = extract_ids [] ist.lfun in
let loc_info = ((if loc' = dloc then loc else loc'),LtacNameCall r) in
- let ist =
+ let ist =
{ lfun=[]; debug=ist.debug; avoid_ids=ids;
- trace = loc_info::ist.trace } in
+ trace = push_trace loc_info ist.trace } in
val_interp ist gl (lookup r)
and interp_tacarg ist gl = function
@@ -1832,7 +1889,7 @@ and interp_tacarg ist gl = function
| Reference r -> interp_ltac_reference dloc false ist gl r
| Integer n -> VInteger n
| IntroPattern ipat -> VIntroPattern (snd (interp_intro_pattern ist gl ipat))
- | ConstrMayEval c -> VConstr (interp_constr_may_eval ist gl c)
+ | ConstrMayEval c -> VConstr ([],interp_constr_may_eval ist gl c)
| MetaIdArg (loc,_,id) -> assert false
| TacCall (loc,r,[]) -> interp_ltac_reference loc true ist gl r
| TacCall (loc,f,l) ->
@@ -1842,18 +1899,18 @@ and interp_tacarg ist gl = function
interp_app loc ist gl fv largs
| TacExternal (loc,com,req,la) ->
interp_external loc ist gl com req (List.map (interp_tacarg ist gl) la)
- | TacFreshId l ->
- let id = interp_fresh_id ist gl l in
+ | TacFreshId l ->
+ let id = pf_interp_fresh_id ist gl l in
VIntroPattern (IntroIdentifier id)
| Tacexp t -> val_interp ist gl t
| TacDynamic(_,t) ->
- let tg = (tag t) in
+ let tg = (Dyn.tag t) in
if tg = "tactic" then
val_interp ist gl (tactic_out t ist)
else if tg = "value" then
value_out t
else if tg = "constr" then
- VConstr (constr_out t)
+ VConstr ([],constr_out t)
else
anomaly_loc (dloc, "Tacinterp.val_interp",
(str "Unknown dynamic: <" ++ str (Dyn.tag t) ++ str ">"))
@@ -1861,21 +1918,28 @@ and interp_tacarg ist gl = function
(* Interprets an application node *)
and interp_app loc ist gl fv largs =
match fv with
- | VFun(trace,olfun,var,body) ->
- let (newlfun,lvar,lval)=head_with_value (var,largs) in
- if lvar=[] then
- let v =
- try
- catch_error trace
- (val_interp { ist with lfun=newlfun@olfun; trace=trace } gl) body
- with e ->
- debugging_exception_step ist false e (fun () -> str "evaluation");
- raise e in
- debugging_step ist (fun () ->
- str "evaluation returns" ++ fnl() ++ pr_value (Some (pf_env gl)) v);
- if lval=[] then v else interp_app loc ist gl v lval
- else
- VFun(trace,newlfun@olfun,lvar,body)
+ (* if var=[] and body has been delayed by val_interp, then body
+ is not a tactic that expects arguments.
+ Otherwise Ltac goes into an infinite loop (val_interp puts
+ a VFun back on body, and then interp_app is called again...) *)
+ | (VFun(trace,olfun,(_::_ as var),body)
+ |VFun(trace,olfun,([] as var),
+ (TacFun _|TacLetIn _|TacMatchGoal _|TacMatch _| TacArg _ as body))) ->
+ let (newlfun,lvar,lval)=head_with_value (var,largs) in
+ if lvar=[] then
+ let v =
+ try
+ catch_error trace
+ (val_interp {ist with lfun=newlfun@olfun; trace=trace} gl) body
+ with e ->
+ debugging_exception_step ist false e (fun () -> str "evaluation");
+ raise e in
+ debugging_step ist
+ (fun () ->
+ str"evaluation returns"++fnl()++pr_value (Some (pf_env gl)) v);
+ if lval=[] then v else interp_app loc ist gl v lval
+ else
+ VFun(trace,newlfun@olfun,lvar,body)
| _ ->
user_err_loc (loc, "Tacinterp.interp_app",
(str"Illegal tactic application."))
@@ -1887,8 +1951,13 @@ and tactic_of_value ist vle g =
| VFun (trace,lfun,[],t) ->
let tac = eval_tactic {ist with lfun=lfun; trace=trace} t in
catch_error trace tac g
- | VFun _ -> error "A fully applied tactic is expected."
- | _ -> raise NotTactic
+ | (VFun _|VRec _) -> error "A fully applied tactic is expected."
+ | VConstr _ -> errorlabstrm "" (str"Value is a term. Expected a tactic.")
+ | VConstr_context _ ->
+ errorlabstrm "" (str"Value is a term context. Expected a tactic.")
+ | VIntroPattern _ ->
+ errorlabstrm "" (str"Value is an intro pattern. Expected a tactic.")
+ | _ -> errorlabstrm "" (str"Expression does not evaluate to a tactic.")
(* Evaluation with FailError catching *)
and eval_with_fail ist is_lazy goal tac =
@@ -1899,9 +1968,9 @@ and eval_with_fail ist is_lazy goal tac =
VRTactic (catch_error trace tac goal)
| a -> a)
with
- | FailError (0,s) | Stdpp.Exc_located(_, FailError (0,s))
+ | FailError (0,s) | Stdpp.Exc_located(_, FailError (0,s))
| Stdpp.Exc_located(_,LtacLocated (_,FailError (0,s))) ->
- raise (Eval_fail s)
+ raise (Eval_fail (Lazy.force s))
| FailError (lvl,s) -> raise (FailError (lvl - 1, s))
| Stdpp.Exc_located(s,FailError (lvl,s')) ->
raise (Stdpp.Exc_located(s,FailError (lvl - 1, s')))
@@ -1933,10 +2002,10 @@ and interp_match_goal ist goal lz lr lmr =
let rec match_next_pattern find_next () =
let (lgoal,ctxt,find_next') = find_next () in
let lctxt = give_context ctxt id in
- try apply_hyps_context ist env lz goal mt lctxt lgoal mhyps hyps
+ try apply_hyps_context ist env lz goal mt lctxt (adjust lgoal) mhyps hyps
with e when is_match_catchable e -> match_next_pattern find_next' () in
match_next_pattern (fun () -> match_subterm_gen app c csr) () in
- let rec apply_match_goal ist env goal nrs lex lpt =
+ let rec apply_match_goal ist env goal nrs lex lpt =
begin
if lex<>[] then db_pattern_rule ist.debug nrs (List.hd lex);
match lpt with
@@ -1974,7 +2043,8 @@ and interp_match_goal ist goal lz lr lmr =
else mt()) ++ str"."))
end in
apply_match_goal ist env goal 0 lmr
- (read_match_rule (fst (constr_list ist env)) lmr)
+ (read_match_rule (fst (extract_ltac_constr_values ist env))
+ ist env (project goal) lmr)
(* Tries to match the hypotheses in a Match Context *)
and apply_hyps_context ist env lz goal mt lctxt lgmatch mhyps hyps =
@@ -1992,7 +2062,7 @@ and apply_hyps_context ist env lz goal mt lctxt lgmatch mhyps hyps =
let id_match = pi1 hyp_match in
let nextlhyps = list_remove_assoc_in_triple id_match lhyps_rest in
apply_hyps_context_rec (lfun@lids) lm nextlhyps tl
- with e when is_match_catchable e ->
+ with e when is_match_catchable e ->
match_next_pattern find_next' in
let init_match_pattern () =
apply_one_mhyp_context ist env goal lmatch hyp_pat lhyps_rest in
@@ -2026,15 +2096,15 @@ and interp_genarg ist gl x =
(interp_intro_pattern ist gl (out_gen globwit_intro_pattern x))
| IdentArgType b ->
in_gen (wit_ident_gen b)
- (interp_fresh_ident ist gl (out_gen (globwit_ident_gen b) x))
+ (pf_interp_fresh_ident ist gl (out_gen (globwit_ident_gen b) x))
| VarArgType ->
in_gen wit_var (interp_hyp ist gl (out_gen globwit_var x))
| RefArgType ->
in_gen wit_ref (pf_interp_reference ist gl (out_gen globwit_ref x))
| SortArgType ->
in_gen wit_sort
- (destSort
- (pf_interp_constr ist gl
+ (destSort
+ (pf_interp_constr ist gl
(RSort (dloc,out_gen globwit_sort x), None)))
| ConstrArgType ->
in_gen wit_constr (pf_interp_constr ist gl (out_gen globwit_constr x))
@@ -2047,15 +2117,17 @@ and interp_genarg ist gl x =
| RedExprArgType ->
in_gen wit_red_expr (pf_interp_red_expr ist gl (out_gen globwit_red_expr x))
| OpenConstrArgType casted ->
- in_gen (wit_open_constr_gen casted)
- (pf_interp_open_constr casted ist gl
+ in_gen (wit_open_constr_gen casted)
+ (interp_open_constr (if casted then Some (pf_concl gl) else None)
+ ist (pf_env gl) (project gl)
(snd (out_gen (globwit_open_constr_gen casted) x)))
| ConstrWithBindingsArgType ->
in_gen wit_constr_with_bindings
- (interp_constr_with_bindings ist gl (out_gen globwit_constr_with_bindings x))
+ (pack_sigma (interp_constr_with_bindings ist (pf_env gl) (project gl)
+ (out_gen globwit_constr_with_bindings x)))
| BindingsArgType ->
in_gen wit_bindings
- (interp_bindings ist gl (out_gen globwit_bindings x))
+ (pack_sigma (interp_bindings ist (pf_env gl) (project gl) (out_gen globwit_bindings x)))
| List0ArgType ConstrArgType -> interp_genarg_constr_list0 ist gl x
| List1ArgType ConstrArgType -> interp_genarg_constr_list1 ist gl x
| List0ArgType VarArgType -> interp_genarg_var_list0 ist gl x
@@ -2064,22 +2136,24 @@ and interp_genarg ist gl x =
| List1ArgType _ -> app_list1 (interp_genarg ist gl) x
| OptArgType _ -> app_opt (interp_genarg ist gl) x
| PairArgType _ -> app_pair (interp_genarg ist gl) (interp_genarg ist gl) x
- | ExtraArgType s ->
+ | ExtraArgType s ->
match tactic_genarg_level s with
- | Some n ->
+ | Some n ->
(* Special treatment of tactic arguments *)
- in_gen (wit_tactic n) (out_gen (globwit_tactic n) x)
- | None ->
+ in_gen (wit_tactic n)
+ (TacArg(valueIn(VFun(ist.trace,ist.lfun,[],
+ out_gen (globwit_tactic n) x))))
+ | None ->
lookup_interp_genarg s ist gl x
and interp_genarg_constr_list0 ist gl x =
let lc = out_gen (wit_list0 globwit_constr) x in
- let lc = pf_interp_constr_list ist gl lc in
+ let lc = pf_apply (interp_constr_list ist) gl lc in
in_gen (wit_list0 wit_constr) lc
and interp_genarg_constr_list1 ist gl x =
let lc = out_gen (wit_list1 globwit_constr) x in
- let lc = pf_interp_constr_list ist gl lc in
+ let lc = pf_apply (interp_constr_list ist) gl lc in
in_gen (wit_list1 wit_constr) lc
and interp_genarg_var_list0 ist gl x =
@@ -2098,7 +2172,7 @@ and interp_match ist g lz constr lmr =
let rec match_next_pattern find_next () =
let (lmatch,ctxt,find_next') = find_next () in
let lctxt = give_context ctxt id in
- let lfun = extend_values_with_bindings lmatch (lctxt@ist.lfun) in
+ let lfun = extend_values_with_bindings (adjust lmatch) (lctxt@ist.lfun) in
try eval_with_fail {ist with lfun=lfun} lz g mt
with e when is_match_catchable e ->
match_next_pattern find_next' () in
@@ -2109,7 +2183,7 @@ and interp_match ist g lz constr lmr =
with e when is_match_catchable e -> apply_match ist csr [])
| (Pat ([],Term c,mt))::tl ->
(try
- let lmatch =
+ let lmatch =
try extended_matches c csr
with e ->
debugging_exception_step ist false e (fun () ->
@@ -2134,14 +2208,14 @@ and interp_match ist g lz constr lmr =
| _ ->
errorlabstrm "Tacinterp.apply_match" (str
"No matching clauses for match.") in
- let csr =
+ let csr =
try interp_ltac_constr ist g constr with e ->
debugging_exception_step ist true e
(fun () -> str "evaluation of the matched expression");
raise e in
- let ilr = read_match_rule (fst (constr_list ist (pf_env g))) lmr in
- let res =
- try apply_match ist csr ilr with e ->
+ let ilr = read_match_rule (fst (extract_ltac_constr_values ist (pf_env g))) ist (pf_env g) (project g) lmr in
+ let res =
+ try apply_match ist csr ilr with e ->
debugging_exception_step ist true e (fun () -> str "match expression");
raise e in
debugging_step ist (fun () ->
@@ -2150,8 +2224,8 @@ and interp_match ist g lz constr lmr =
(* Interprets tactic expressions : returns a "constr" *)
and interp_ltac_constr ist gl e =
- let result =
- try val_interp ist gl e with Not_found ->
+ let result =
+ try val_interp ist gl e with Not_found ->
debugging_step ist (fun () ->
str "evaluation failed for" ++ fnl() ++
Pptactic.pr_glob_tactic (pf_env gl) e);
@@ -2160,11 +2234,13 @@ and interp_ltac_constr ist gl e =
let cresult = constr_of_value (pf_env gl) result in
debugging_step ist (fun () ->
Pptactic.pr_glob_tactic (pf_env gl) e ++ fnl() ++
- str " has value " ++ fnl() ++ print_constr_env (pf_env gl) cresult);
- cresult
+ str " has value " ++ fnl() ++
+ pr_constr_under_binders_env (pf_env gl) cresult);
+ if fst cresult <> [] then raise Not_found;
+ snd cresult
with Not_found ->
errorlabstrm ""
- (str "Must evaluate to a term" ++ fnl() ++
+ (str "Must evaluate to a closed term" ++ fnl() ++
str "offending expression: " ++ fnl() ++
Pptactic.pr_glob_tactic (pf_env gl) e ++ fnl() ++ str "this is a " ++
(match result with
@@ -2173,7 +2249,7 @@ and interp_ltac_constr ist gl e =
(str "VFun with body " ++ fnl() ++
Pptactic.pr_glob_tactic (pf_env gl) b ++ fnl() ++
str "instantiated arguments " ++ fnl() ++
- List.fold_right
+ List.fold_right
(fun p s ->
let (i,v) = p in str (string_of_id i) ++ str ", " ++ s)
il (str "") ++
@@ -2194,63 +2270,71 @@ and interp_ltac_constr ist gl e =
(* Interprets tactic expressions : returns a "tactic" *)
and interp_tactic ist tac gl =
- try tactic_of_value ist (val_interp ist gl tac) gl
- with NotTactic -> errorlabstrm "" (str "Not a tactic.")
+ tactic_of_value ist (val_interp ist gl tac) gl
(* Interprets a primitive tactic *)
-and interp_atomic ist gl = function
+and interp_atomic ist gl tac =
+ let env = pf_env gl and sigma = project gl in
+ match tac with
(* Basic tactics *)
| TacIntroPattern l ->
- h_intro_patterns (List.map (interp_intro_pattern ist gl) l)
+ h_intro_patterns (interp_intro_pattern_list_as_list ist gl l)
| TacIntrosUntil hyp ->
h_intros_until (interp_quantified_hypothesis ist hyp)
| TacIntroMove (ido,hto) ->
- h_intro_move (Option.map (interp_fresh_ident ist gl) ido)
+ h_intro_move (Option.map (interp_fresh_ident ist env) ido)
(interp_move_location ist gl hto)
| TacAssumption -> h_assumption
| TacExact c -> h_exact (pf_interp_casted_constr ist gl c)
| TacExactNoCheck c -> h_exact_no_check (pf_interp_constr ist gl c)
| TacVmCastNoCheck c -> h_vm_cast_no_check (pf_interp_constr ist gl c)
- | TacApply (a,ev,cb,None) ->
- h_apply a ev (List.map (interp_open_constr_with_bindings ist gl) cb)
- | TacApply (a,ev,cb,Some cl) ->
- h_apply_in a ev (List.map (interp_open_constr_with_bindings ist gl) cb)
- (interp_in_hyp_as ist gl cl)
+ | TacApply (a,ev,cb,cl) ->
+ let sigma, l =
+ list_fold_map (interp_open_constr_with_bindings_loc ist env) sigma cb
+ in
+ let tac = match cl with
+ | None -> h_apply a ev
+ | Some cl ->
+ (fun l -> h_apply_in a ev l (interp_in_hyp_as ist gl cl)) in
+ tclWITHHOLES ev tac sigma l
| TacElim (ev,cb,cbo) ->
- h_elim ev (interp_constr_with_bindings ist gl cb)
- (Option.map (interp_constr_with_bindings ist gl) cbo)
+ let sigma, cb = interp_constr_with_bindings ist env sigma cb in
+ let sigma, cbo = Option.fold_map (interp_constr_with_bindings ist env) sigma cbo in
+ tclWITHHOLES ev (h_elim ev cb) sigma cbo
| TacElimType c -> h_elim_type (pf_interp_type ist gl c)
- | TacCase (ev,cb) -> h_case ev (interp_constr_with_bindings ist gl cb)
+ | TacCase (ev,cb) ->
+ let sigma, cb = interp_constr_with_bindings ist env sigma cb in
+ tclWITHHOLES ev (h_case ev) sigma cb
| TacCaseType c -> h_case_type (pf_interp_type ist gl c)
- | TacFix (idopt,n) -> h_fix (Option.map (interp_fresh_ident ist gl) idopt) n
+ | TacFix (idopt,n) -> h_fix (Option.map (interp_fresh_ident ist env) idopt) n
| TacMutualFix (b,id,n,l) ->
- let f (id,n,c) = (interp_fresh_ident ist gl id,n,pf_interp_type ist gl c)
- in h_mutual_fix b (interp_fresh_ident ist gl id) n (List.map f l)
- | TacCofix idopt -> h_cofix (Option.map (interp_fresh_ident ist gl) idopt)
+ let f (id,n,c) = (interp_fresh_ident ist env id,n,pf_interp_type ist gl c)
+ in h_mutual_fix b (interp_fresh_ident ist env id) n (List.map f l)
+ | TacCofix idopt -> h_cofix (Option.map (interp_fresh_ident ist env) idopt)
| TacMutualCofix (b,id,l) ->
- let f (id,c) = (interp_fresh_ident ist gl id,pf_interp_type ist gl c) in
- h_mutual_cofix b (interp_fresh_ident ist gl id) (List.map f l)
+ let f (id,c) = (interp_fresh_ident ist env id,pf_interp_type ist gl c) in
+ h_mutual_cofix b (interp_fresh_ident ist env id) (List.map f l)
| TacCut c -> h_cut (pf_interp_type ist gl c)
| TacAssert (t,ipat,c) ->
- let c = (if t=None then interp_constr else interp_type) ist (project gl) (pf_env gl) c in
- abstract_tactic (TacAssert (t,ipat,inj_open c))
+ let c = (if t=None then interp_constr else interp_type) ist env sigma c in
+ abstract_tactic (TacAssert (t,ipat,c))
(Tactics.forward (Option.map (interp_tactic ist) t)
(Option.map (interp_intro_pattern ist gl) ipat) c)
| TacGeneralize cl ->
- h_generalize_gen
- (pf_interp_constr_with_occurrences_and_name_as_list ist gl cl)
+ let sigma, cl = interp_constr_with_occurrences_and_name_as_list ist env sigma cl in
+ tclWITHHOLES false (h_generalize_gen) sigma cl
| TacGeneralizeDep c -> h_generalize_dep (pf_interp_constr ist gl c)
| TacLetTac (na,c,clp,b) ->
let clp = interp_clause ist gl clp in
- h_let_tac b (interp_fresh_name ist gl na) (pf_interp_constr ist gl c) clp
+ h_let_tac b (interp_fresh_name ist env na) (pf_interp_constr ist gl c) clp
(* Automation tactics *)
- | TacTrivial (lems,l) ->
- Auto.h_trivial (pf_interp_constr_list ist gl lems)
+ | TacTrivial (lems,l) ->
+ Auto.h_trivial (interp_constr_list ist env sigma lems)
(Option.map (List.map (interp_hint_base ist)) l)
| TacAuto (n,lems,l) ->
Auto.h_auto (Option.map (interp_int_or_var ist) n)
- (pf_interp_constr_list ist gl lems)
+ (interp_constr_list ist env sigma lems)
(Option.map (List.map (interp_hint_base ist)) l)
| TacAutoTDB n -> Dhyp.h_auto_tdb n
| TacDestructHyp (b,id) -> Dhyp.h_destructHyp b (interp_hyp ist gl id)
@@ -2258,19 +2342,23 @@ and interp_atomic ist gl = function
| TacSuperAuto (n,l,b1,b2) -> Auto.h_superauto n l b1 b2
| TacDAuto (n,p,lems) ->
Auto.h_dauto (Option.map (interp_int_or_var ist) n,p)
- (pf_interp_constr_list ist gl lems)
+ (interp_constr_list ist env sigma lems)
(* Derived basic tactics *)
| TacSimpleInductionDestruct (isrec,h) ->
h_simple_induction_destruct isrec (interp_quantified_hypothesis ist h)
- | TacInductionDestruct (isrec,ev,l) ->
- h_induction_destruct ev isrec
- (List.map (fun (lc,cbo,(ipato,ipats),cls) ->
- (List.map (interp_induction_arg ist gl) lc,
- Option.map (interp_constr_with_bindings ist gl) cbo,
- (Option.map (interp_intro_pattern ist gl) ipato,
- Option.map (interp_intro_pattern ist gl) ipats),
- Option.map (interp_clause ist gl) cls)) l)
+ | TacInductionDestruct (isrec,ev,(l,cls)) ->
+ let sigma, l =
+ list_fold_map (fun sigma (lc,cbo,(ipato,ipats)) ->
+ let sigma,lc =
+ list_fold_map (interp_induction_arg ist gl) sigma lc in
+ let sigma,cbo =
+ Option.fold_map (interp_constr_with_bindings ist env) sigma cbo in
+ (sigma,(lc,cbo,
+ (Option.map (interp_intro_pattern ist gl) ipato,
+ Option.map (interp_intro_pattern ist gl) ipats)))) sigma l in
+ let cls = Option.map (interp_clause ist gl) cls in
+ tclWITHHOLES ev (h_induction_destruct isrec ev) sigma (l,cls)
| TacDoubleInduction (h1,h2) ->
let h1 = interp_quantified_hypothesis ist h1 in
let h2 = interp_quantified_hypothesis ist h2 in
@@ -2280,8 +2368,9 @@ and interp_atomic ist gl = function
| TacDecompose (l,c) ->
let l = List.map (interp_inductive ist) l in
Elim.h_decompose l (pf_interp_constr ist gl c)
- | TacSpecialize (n,l) ->
- h_specialize n (interp_constr_with_bindings ist gl l)
+ | TacSpecialize (n,cb) ->
+ let sigma, cb = interp_constr_with_bindings ist env sigma cb in
+ tclWITHHOLES false (h_specialize n) sigma cb
| TacLApply c -> h_lapply (pf_interp_constr ist gl c)
(* Context management *)
@@ -2290,50 +2379,64 @@ and interp_atomic ist gl = function
| TacMove (dep,id1,id2) ->
h_move dep (interp_hyp ist gl id1) (interp_move_location ist gl id2)
| TacRename l ->
- h_rename (List.map (fun (id1,id2) ->
- interp_hyp ist gl id1,
- interp_fresh_ident ist gl (snd id2)) l)
+ h_rename (List.map (fun (id1,id2) ->
+ interp_hyp ist gl id1,
+ interp_fresh_ident ist env (snd id2)) l)
| TacRevert l -> h_revert (interp_hyp_list ist gl l)
(* Constructors *)
- | TacLeft (ev,bl) -> h_left ev (interp_bindings ist gl bl)
- | TacRight (ev,bl) -> h_right ev (interp_bindings ist gl bl)
- | TacSplit (ev,_,bl) -> h_split ev (interp_bindings ist gl bl)
+ | TacLeft (ev,bl) ->
+ let sigma, bl = interp_bindings ist env sigma bl in
+ tclWITHHOLES ev (h_left ev) sigma bl
+ | TacRight (ev,bl) ->
+ let sigma, bl = interp_bindings ist env sigma bl in
+ tclWITHHOLES ev (h_right ev) sigma bl
+ | TacSplit (ev,_,bll) ->
+ let sigma, bll = list_fold_map (interp_bindings ist env) sigma bll in
+ tclWITHHOLES ev (h_split ev) sigma bll
| TacAnyConstructor (ev,t) ->
abstract_tactic (TacAnyConstructor (ev,t))
(Tactics.any_constructor ev (Option.map (interp_tactic ist) t))
| TacConstructor (ev,n,bl) ->
- h_constructor ev (skip_metaid n) (interp_bindings ist gl bl)
+ let sigma, bl = interp_bindings ist env sigma bl in
+ tclWITHHOLES ev (h_constructor ev (skip_metaid n)) sigma bl
(* Conversion *)
| TacReduce (r,cl) ->
h_reduce (pf_interp_red_expr ist gl r) (interp_clause ist gl cl)
- | TacChange (occl,c,cl) ->
- h_change (Option.map (pf_interp_constr_with_occurrences ist gl) occl)
- (if occl = None & (cl.onhyps = None or cl.onhyps = Some []) &
+ | TacChange (None,c,cl) ->
+ h_change None
+ (if (cl.onhyps = None or cl.onhyps = Some []) &
(cl.concl_occs = all_occurrences_expr or
cl.concl_occs = no_occurrences_expr)
- then pf_interp_type ist gl c
+ then pf_interp_type ist gl c
else pf_interp_constr ist gl c)
(interp_clause ist gl cl)
+ | TacChange (Some op,c,cl) ->
+ let sign,op = interp_typed_pattern ist env sigma op in
+ h_change (Some op)
+ (pf_interp_constr ist (extend_gl_hyps gl sign) c)
+ (interp_clause ist gl cl)
(* Equivalence relations *)
| TacReflexivity -> h_reflexivity
| TacSymmetry c -> h_symmetry (interp_clause ist gl c)
- | TacTransitivity c -> h_transitivity (pf_interp_constr ist gl c)
+ | TacTransitivity c -> h_transitivity (Option.map (pf_interp_constr ist gl) c)
(* Equality and inversion *)
- | TacRewrite (ev,l,cl,by) ->
- Equality.general_multi_multi_rewrite ev
- (List.map (fun (b,m,c) -> (b,m,interp_open_constr_with_bindings ist gl c)) l)
- (interp_clause ist gl cl)
- (Option.map (interp_tactic ist) by)
+ | TacRewrite (ev,l,cl,by) ->
+ let l = List.map (fun (b,m,c) ->
+ let f env sigma = interp_open_constr_with_bindings ist env sigma c in
+ (b,m,f)) l in
+ let cl = interp_clause ist gl cl in
+ Equality.general_multi_multi_rewrite ev l cl
+ (Option.map (fun by -> tclCOMPLETE (interp_tactic ist by), Equality.Naive) by)
| TacInversion (DepInversion (k,c,ids),hyp) ->
Inv.dinv k (Option.map (pf_interp_constr ist gl) c)
(Option.map (interp_intro_pattern ist gl) ids)
(interp_declared_or_quantified_hypothesis ist gl hyp)
| TacInversion (NonDepInversion (k,idl,ids),hyp) ->
- Inv.inv_clause k
+ Inv.inv_clause k
(Option.map (interp_intro_pattern ist gl) ids)
(interp_hyp_list ist gl idl)
(interp_declared_or_quantified_hypothesis ist gl hyp)
@@ -2349,79 +2452,94 @@ and interp_atomic ist gl = function
abstract_extended_tactic opn args (tac args)
| TacAlias (loc,s,l,(_,body)) -> fun gl ->
let rec f x = match genarg_tag x with
- | IntArgType ->
+ | IntArgType ->
VInteger (out_gen globwit_int x)
| IntOrVarArgType ->
mk_int_or_var_value ist (out_gen globwit_int_or_var x)
| PreIdentArgType ->
failwith "pre-identifiers cannot be bound"
| IntroPatternArgType ->
- VIntroPattern
+ VIntroPattern
(snd (interp_intro_pattern ist gl (out_gen globwit_intro_pattern x)))
| IdentArgType b ->
- VIntroPattern
- (IntroIdentifier
- (interp_fresh_ident ist gl (out_gen (globwit_ident_gen b) x)))
+ value_of_ident (interp_fresh_ident ist env
+ (out_gen (globwit_ident_gen b) x))
| VarArgType ->
mk_hyp_value ist gl (out_gen globwit_var x)
- | RefArgType ->
- VConstr (constr_of_global
+ | RefArgType ->
+ VConstr ([],constr_of_global
(pf_interp_reference ist gl (out_gen globwit_ref x)))
- | SortArgType ->
- VConstr (mkSort (interp_sort (out_gen globwit_sort x)))
+ | SortArgType ->
+ VConstr ([],mkSort (interp_sort (out_gen globwit_sort x)))
| ConstrArgType ->
mk_constr_value ist gl (out_gen globwit_constr x)
| ConstrMayEvalArgType ->
VConstr
- (interp_constr_may_eval ist gl (out_gen globwit_constr_may_eval x))
+ ([],interp_constr_may_eval ist gl (out_gen globwit_constr_may_eval x))
| ExtraArgType s when tactic_genarg_level s <> None ->
(* Special treatment of tactic arguments *)
- val_interp ist gl
+ val_interp ist gl
(out_gen (globwit_tactic (Option.get (tactic_genarg_level s))) x)
- | List0ArgType ConstrArgType ->
+ | List0ArgType ConstrArgType ->
let wit = wit_list0 globwit_constr in
VList (List.map (mk_constr_value ist gl) (out_gen wit x))
- | List0ArgType VarArgType ->
+ | List0ArgType VarArgType ->
let wit = wit_list0 globwit_var in
VList (List.map (mk_hyp_value ist gl) (out_gen wit x))
- | List0ArgType IntArgType ->
+ | List0ArgType IntArgType ->
let wit = wit_list0 globwit_int in
VList (List.map (fun x -> VInteger x) (out_gen wit x))
- | List0ArgType IntOrVarArgType ->
+ | List0ArgType IntOrVarArgType ->
let wit = wit_list0 globwit_int_or_var in
VList (List.map (mk_int_or_var_value ist) (out_gen wit x))
- | List1ArgType ConstrArgType ->
+ | List0ArgType (IdentArgType b) ->
+ let wit = wit_list0 (globwit_ident_gen b) in
+ let mk_ident x = value_of_ident (interp_fresh_ident ist env x) in
+ VList (List.map mk_ident (out_gen wit x))
+ | List0ArgType IntroPatternArgType ->
+ let wit = wit_list0 globwit_intro_pattern in
+ let mk_ipat x = VIntroPattern (snd (interp_intro_pattern ist gl x)) in
+ VList (List.map mk_ipat (out_gen wit x))
+ | List1ArgType ConstrArgType ->
let wit = wit_list1 globwit_constr in
VList (List.map (mk_constr_value ist gl) (out_gen wit x))
- | List1ArgType VarArgType ->
+ | List1ArgType VarArgType ->
let wit = wit_list1 globwit_var in
VList (List.map (mk_hyp_value ist gl) (out_gen wit x))
- | List1ArgType IntArgType ->
+ | List1ArgType IntArgType ->
let wit = wit_list1 globwit_int in
VList (List.map (fun x -> VInteger x) (out_gen wit x))
- | List1ArgType IntOrVarArgType ->
+ | List1ArgType IntOrVarArgType ->
let wit = wit_list1 globwit_int_or_var in
VList (List.map (mk_int_or_var_value ist) (out_gen wit x))
+ | List1ArgType (IdentArgType b) ->
+ let wit = wit_list1 (globwit_ident_gen b) in
+ let mk_ident x = value_of_ident (interp_fresh_ident ist env x) in
+ VList (List.map mk_ident (out_gen wit x))
+ | List1ArgType IntroPatternArgType ->
+ let wit = wit_list1 globwit_intro_pattern in
+ let mk_ipat x = VIntroPattern (snd (interp_intro_pattern ist gl x)) in
+ VList (List.map mk_ipat (out_gen wit x))
| StringArgType | BoolArgType
- | QuantHypArgType | RedExprArgType
- | OpenConstrArgType _ | ConstrWithBindingsArgType
- | ExtraArgType _ | BindingsArgType
- | OptArgType _ | PairArgType _
- | List0ArgType _ | List1ArgType _
+ | QuantHypArgType | RedExprArgType
+ | OpenConstrArgType _ | ConstrWithBindingsArgType
+ | ExtraArgType _ | BindingsArgType
+ | OptArgType _ | PairArgType _
+ | List0ArgType _ | List1ArgType _
-> error "This generic type is not supported in alias."
-
+
in
let lfun = (List.map (fun (x,c) -> (x,f c)) l)@ist.lfun in
- let trace = (loc,LtacNotationCall s)::ist.trace in
+ let trace = push_trace (loc,LtacNotationCall s) ist.trace in
interp_tactic { ist with lfun=lfun; trace=trace } body gl
let make_empty_glob_sign () =
- { ltacvars = ([],[]); ltacrecvars = [];
+ { ltacvars = ([],[]); ltacrecvars = [];
gsigma = Evd.empty; genv = Global.env() }
(* Initial call for interpretation *)
-let interp_tac_gen lfun avoid_ids debug t gl =
- interp_tactic { lfun=lfun; avoid_ids=avoid_ids; debug=debug; trace=[] }
+let interp_tac_gen lfun avoid_ids debug t gl =
+ interp_tactic { lfun=lfun; avoid_ids=avoid_ids; debug=debug; trace=[] }
(intern_tactic {
ltacvars = (List.map fst lfun, []); ltacrecvars = [];
gsigma = project gl; genv = pf_env gl } t) gl
@@ -2433,17 +2551,17 @@ let eval_tactic t gls =
let interp t = interp_tac_gen [] [] (get_debug()) t
let eval_ltac_constr gl t =
- interp_ltac_constr
+ interp_ltac_constr
{ lfun=[]; avoid_ids=[]; debug=get_debug(); trace=[] } gl
(intern_tactic (make_empty_glob_sign ()) t )
(* Hides interpretation for pretty-print *)
let hide_interp t ot gl =
- let ist = { ltacvars = ([],[]); ltacrecvars = [];
+ let ist = { ltacvars = ([],[]); ltacrecvars = [];
gsigma = project gl; genv = pf_env gl } in
let te = intern_tactic ist t in
let t = eval_tactic te in
- match ot with
+ match ot with
| None -> abstract_tactic_expr (TacArg (Tacexp te)) t gl
| Some t' ->
abstract_tactic_expr ~dflt:true (TacArg (Tacexp te)) (tclTHEN t t') gl
@@ -2487,13 +2605,13 @@ let subst_or_var f = function
let subst_located f (_loc,id) = (dloc,f id)
-let subst_reference subst =
+let subst_reference subst =
subst_or_var (subst_located (subst_kn subst))
(*CSC: subst_global_reference is used "only" for RefArgType, that propagates
to the syntactic non-terminals "global", used in commands such as
- Print. It is also used for non-evaluable references. *)
-let subst_global_reference subst =
+ Print. It is also used for non-evaluable references. *)
+let subst_global_reference subst =
let subst_global ref =
let ref',t' = subst_global subst ref in
if not (eq_constr (constr_of_global ref') t') then
@@ -2508,7 +2626,7 @@ let subst_evaluable subst =
let subst_eval_ref = subst_evaluable_reference subst in
subst_or_var (subst_and_short_name subst_eval_ref)
-let subst_unfold subst (l,e) =
+let subst_unfold subst (l,e) =
(l,subst_evaluable subst e)
let subst_flag subst red =
@@ -2516,13 +2634,19 @@ let subst_flag subst red =
let subst_constr_with_occurrences subst (l,c) = (l,subst_rawconstr subst c)
+let subst_rawconstr_or_pattern subst (c,p) =
+ (subst_rawconstr subst c,subst_pattern subst p)
+
+let subst_pattern_with_occurrences subst (l,p) =
+ (l,subst_rawconstr_or_pattern subst p)
+
let subst_redexp subst = function
| Unfold l -> Unfold (List.map (subst_unfold subst) l)
| Fold l -> Fold (List.map (subst_rawconstr subst) l)
| Cbv f -> Cbv (subst_flag subst f)
| Lazy f -> Lazy (subst_flag subst f)
| Pattern l -> Pattern (List.map (subst_constr_with_occurrences subst) l)
- | Simpl o -> Simpl (Option.map (subst_constr_with_occurrences subst) o)
+ | Simpl o -> Simpl (Option.map (subst_pattern_with_occurrences subst) o)
| (Red _ | Hnf | ExtraRedExpr _ | CbvVm as r) -> r
let subst_raw_may_eval subst = function
@@ -2532,8 +2656,8 @@ let subst_raw_may_eval subst = function
| ConstrTerm c -> ConstrTerm (subst_rawconstr subst c)
let subst_match_pattern subst = function
- | Subterm (b,ido,pc) -> Subterm (b,ido,subst_pattern subst pc)
- | Term pc -> Term (subst_pattern subst pc)
+ | Subterm (b,ido,pc) -> Subterm (b,ido,(subst_rawconstr_or_pattern subst pc))
+ | Term pc -> Term (subst_rawconstr_or_pattern subst pc)
let rec subst_match_goal_hyps subst = function
| Hyp (locs,mp) :: tl ->
@@ -2584,10 +2708,10 @@ let rec subst_atomic subst (t:glob_atomic_tactic_expr) = match t with
(* Derived basic tactics *)
| TacSimpleInductionDestruct (isrec,h) as x -> x
- | TacInductionDestruct (isrec,ev,l) ->
- TacInductionDestruct (isrec,ev,List.map (fun (lc,cbo,ids,cls) ->
+ | TacInductionDestruct (isrec,ev,(l,cls)) ->
+ TacInductionDestruct (isrec,ev,(List.map (fun (lc,cbo,ids) ->
List.map (subst_induction_arg subst) lc,
- Option.map (subst_raw_with_bindings subst) cbo, ids, cls) l)
+ Option.map (subst_raw_with_bindings subst) cbo, ids) l, cls))
| TacDoubleInduction (h1,h2) as x -> x
| TacDecomposeAnd c -> TacDecomposeAnd (subst_rawconstr subst c)
| TacDecomposeOr c -> TacDecomposeOr (subst_rawconstr subst c)
@@ -2607,23 +2731,23 @@ let rec subst_atomic subst (t:glob_atomic_tactic_expr) = match t with
(* Constructors *)
| TacLeft (ev,bl) -> TacLeft (ev,subst_bindings subst bl)
| TacRight (ev,bl) -> TacRight (ev,subst_bindings subst bl)
- | TacSplit (ev,b,bl) -> TacSplit (ev,b,subst_bindings subst bl)
+ | TacSplit (ev,b,bll) -> TacSplit (ev,b,List.map (subst_bindings subst) bll)
| TacAnyConstructor (ev,t) -> TacAnyConstructor (ev,Option.map (subst_tactic subst) t)
| TacConstructor (ev,n,bl) -> TacConstructor (ev,n,subst_bindings subst bl)
(* Conversion *)
| TacReduce (r,cl) -> TacReduce (subst_redexp subst r, cl)
- | TacChange (occl,c,cl) ->
- TacChange (Option.map (subst_constr_with_occurrences subst) occl,
+ | TacChange (op,c,cl) ->
+ TacChange (Option.map (subst_rawconstr_or_pattern subst) op,
subst_rawconstr subst c, cl)
(* Equivalence relations *)
| TacReflexivity | TacSymmetry _ as x -> x
- | TacTransitivity c -> TacTransitivity (subst_rawconstr subst c)
+ | TacTransitivity c -> TacTransitivity (Option.map (subst_rawconstr subst) c)
(* Equality and inversion *)
- | TacRewrite (ev,l,cl,by) ->
- TacRewrite (ev,
+ | TacRewrite (ev,l,cl,by) ->
+ TacRewrite (ev,
List.map (fun (b,m,c) ->
b,m,subst_raw_with_bindings subst c) l,
cl,Option.map (subst_tactic subst) by)
@@ -2677,14 +2801,14 @@ and subst_tacarg subst = function
| MetaIdArg (_loc,_,_) -> assert false
| TacCall (_loc,f,l) ->
TacCall (_loc, subst_reference subst f, List.map (subst_tacarg subst) l)
- | TacExternal (_loc,com,req,la) ->
+ | TacExternal (_loc,com,req,la) ->
TacExternal (_loc,com,req,List.map (subst_tacarg subst) la)
| (TacVoid | IntroPattern _ | Integer _ | TacFreshId _) as x -> x
| Tacexp t -> Tacexp (subst_tactic subst t)
| TacDynamic(the_loc,t) as x ->
- (match tag t with
+ (match Dyn.tag t with
| "tactic" | "value" -> x
- | "constr" ->
+ | "constr" ->
TacDynamic(the_loc, constr_in (subst_mps subst (constr_out t)))
| s -> anomaly_loc (dloc, "Tacinterp.val_interp",
str "Unknown dynamic: <" ++ str s ++ str ">"))
@@ -2709,11 +2833,11 @@ and subst_genarg subst (x:glob_generic_argument) =
| PreIdentArgType -> in_gen globwit_pre_ident (out_gen globwit_pre_ident x)
| IntroPatternArgType ->
in_gen globwit_intro_pattern (out_gen globwit_intro_pattern x)
- | IdentArgType b ->
+ | IdentArgType b ->
in_gen (globwit_ident_gen b) (out_gen (globwit_ident_gen b) x)
| VarArgType -> in_gen globwit_var (out_gen globwit_var x)
| RefArgType ->
- in_gen globwit_ref (subst_global_reference subst
+ in_gen globwit_ref (subst_global_reference subst
(out_gen globwit_ref x))
| SortArgType ->
in_gen globwit_sort (out_gen globwit_sort x)
@@ -2723,7 +2847,7 @@ and subst_genarg subst (x:glob_generic_argument) =
in_gen globwit_constr_may_eval (subst_raw_may_eval subst (out_gen globwit_constr_may_eval x))
| QuantHypArgType ->
in_gen globwit_quant_hyp
- (subst_declared_or_quantified_hypothesis subst
+ (subst_declared_or_quantified_hypothesis subst
(out_gen globwit_quant_hyp x))
| RedExprArgType ->
in_gen globwit_red_expr (subst_redexp subst (out_gen globwit_red_expr x))
@@ -2742,11 +2866,11 @@ and subst_genarg subst (x:glob_generic_argument) =
| PairArgType _ -> app_pair (subst_genarg subst) (subst_genarg subst) x
| ExtraArgType s ->
match tactic_genarg_level s with
- | Some n ->
+ | Some n ->
(* Special treatment of tactic arguments *)
in_gen (globwit_tactic n)
(subst_tactic subst (out_gen (globwit_tactic n) x))
- | None ->
+ | None ->
lookup_genarg_subst s subst x
(***************************************************************************)
@@ -2764,10 +2888,10 @@ let replace (kn,td) = mactab := Gmap.add kn td (Gmap.remove kn !mactab)
type tacdef_kind = | NewTac of identifier
| UpdateTac of ltac_constant
-let load_md i ((sp,kn),defs) =
+let load_md i ((sp,kn),(local,defs)) =
let dp,_ = repr_path sp in
let mp,dir,_ = repr_kn kn in
- List.iter (fun (id,t) ->
+ List.iter (fun (id,t) ->
match id with
NewTac id ->
let sp = Libnames.make_path dp id in
@@ -2775,11 +2899,11 @@ let load_md i ((sp,kn),defs) =
Nametab.push_tactic (Until i) sp kn;
add (kn,t)
| UpdateTac kn -> replace (kn,t)) defs
-
-let open_md i((sp,kn),defs) =
+
+let open_md i ((sp,kn),(local,defs)) =
let dp,_ = repr_path sp in
let mp,dir,_ = repr_kn kn in
- List.iter (fun (id,t) ->
+ List.iter (fun (id,t) ->
match id with
NewTac id ->
let sp = Libnames.make_path dp id in
@@ -2789,13 +2913,17 @@ let open_md i((sp,kn),defs) =
let cache_md x = load_md 1 x
-let subst_kind subst id =
+let subst_kind subst id =
match id with
| NewTac _ -> id
- | UpdateTac kn -> UpdateTac (Mod_subst.subst_kn subst kn)
+ | UpdateTac kn -> UpdateTac (subst_kn subst kn)
+
+let subst_md (subst,(local,defs)) =
+ (local,
+ List.map (fun (id,t) -> (subst_kind subst id,subst_tactic subst t)) defs)
-let subst_md (_,subst,defs) =
- List.map (fun (id,t) -> (subst_kind subst id,subst_tactic subst t)) defs
+let classify_md (local,defs as o) =
+ if local then Dispose else Substitute o
let (inMD,outMD) =
declare_object {(default_object "TAC-DEFINITION") with
@@ -2803,8 +2931,7 @@ let (inMD,outMD) =
load_function = load_md;
open_function = open_md;
subst_function = subst_md;
- classify_function = (fun (_,o) -> Substitute o);
- export_function = (fun x -> Some x)}
+ classify_function = classify_md}
let print_ltac id =
try
@@ -2822,18 +2949,18 @@ open Libnames
(* Adds a definition for tactics in the table *)
let make_absolute_name ident repl =
let loc = loc_of_reference ident in
- try
- let id, kn =
+ try
+ let id, kn =
if repl then None, Nametab.locate_tactic (snd (qualid_of_reference ident))
- else let id = Pcoq.coerce_global_to_id ident in
- Some id, Lib.make_kn id
+ else let id = coerce_reference_to_id ident in
+ Some id, Lib.make_kn id
in
if Gmap.mem kn !mactab then
if repl then id, kn
else
user_err_loc (loc,"Tacinterp.add_tacdef",
str "There is already an Ltac named " ++ pr_reference ident ++ str".")
- else if is_atomic_kn kn then
+ else if is_atomic_kn kn then
user_err_loc (loc,"Tacinterp.add_tacdef",
str "Reserved Ltac name " ++ pr_reference ident ++ str".")
else id, kn
@@ -2841,21 +2968,12 @@ let make_absolute_name ident repl =
user_err_loc (loc,"Tacinterp.add_tacdef",
str "There is no Ltac named " ++ pr_reference ident ++ str".")
-let rec filter_map f l =
- let rec aux acc = function
- [] -> acc
- | hd :: tl ->
- match f hd with
- Some x -> aux (x :: acc) tl
- | None -> aux acc tl
- in aux [] l
-
-let add_tacdef isrec tacl =
+let add_tacdef local isrec tacl =
let rfun = List.map (fun (ident, b, _) -> make_absolute_name ident b) tacl in
let ist =
- {(make_empty_glob_sign()) with ltacrecvars =
- if isrec then filter_map
- (function (Some id, qid) -> Some (id, qid) | (None, _) -> None) rfun
+ {(make_empty_glob_sign()) with ltacrecvars =
+ if isrec then list_map_filter
+ (function (Some id, qid) -> Some (id, qid) | (None, _) -> None) rfun
else []} in
let gtacl =
List.map2 (fun (_,b,def) (id, qid) ->
@@ -2864,11 +2982,12 @@ let add_tacdef isrec tacl =
(k, t))
tacl rfun in
let id0 = fst (List.hd rfun) in
- let _ = match id0 with Some id0 -> ignore(Lib.add_leaf id0 (inMD gtacl))
- | _ -> Lib.add_anonymous_leaf (inMD gtacl) in
+ let _ = match id0 with
+ | Some id0 -> ignore(Lib.add_leaf id0 (inMD (local,gtacl)))
+ | _ -> Lib.add_anonymous_leaf (inMD (local,gtacl)) in
List.iter
- (fun (id,b,_) ->
- Flags.if_verbose msgnl (Libnames.pr_reference id ++
+ (fun (id,b,_) ->
+ Flags.if_verbose msgnl (Libnames.pr_reference id ++
(if b then str " is redefined"
else str " is defined")))
tacl
@@ -2879,13 +2998,13 @@ let add_tacdef isrec tacl =
let glob_tactic x =
Flags.with_option strict_check (intern_tactic (make_empty_glob_sign ())) x
-let glob_tactic_env l env x =
+let glob_tactic_env l env x =
Flags.with_option strict_check
(intern_tactic
{ ltacvars = (l,[]); ltacrecvars = []; gsigma = Evd.empty; genv = env })
x
-let interp_redexp env sigma r =
+let interp_redexp env sigma r =
let ist = { lfun=[]; avoid_ids=[]; debug=get_debug (); trace=[] } in
let gist = {(make_empty_glob_sign ()) with genv = env; gsigma = sigma } in
interp_red_expr ist sigma env (intern_red_expr gist r)
@@ -2894,11 +3013,14 @@ let interp_redexp env sigma r =
(* Embed tactics in raw or glob tactic expr *)
let globTacticIn t = TacArg (TacDynamic (dummy_loc,tactic_in t))
-let tacticIn t = globTacticIn (fun ist -> glob_tactic (t ist))
+let tacticIn t =
+ globTacticIn (fun ist ->
+ try glob_tactic (t ist)
+ with e -> raise (AnomalyOnError ("Incorrect tactic expression", e)))
let tacticOut = function
| TacArg (TacDynamic (_,d)) ->
- if (tag d) = "tactic" then
+ if (Dyn.tag d) = "tactic" then
tactic_out d
else
anomalylabstrm "tacticOut" (str "Dynamic tag should be tactic")
@@ -2910,14 +3032,12 @@ let tacticOut = function
(* Backwarding recursive needs of tactic glob/interp/eval functions *)
let _ = Auto.set_extern_interp
- (fun l ->
- let l = List.map (fun (id,c) -> (id,VConstr c)) l in
+ (fun l ->
+ let l = List.map (fun (id,c) -> (id,VConstr ([],c))) l in
interp_tactic {lfun=l;avoid_ids=[];debug=get_debug(); trace=[]})
-let _ = Auto.set_extern_intern_tac
+let _ = Auto.set_extern_intern_tac
(fun l ->
Flags.with_option strict_check
(intern_tactic {(make_empty_glob_sign()) with ltacvars=(l,[])}))
let _ = Auto.set_extern_subst_tactic subst_tactic
let _ = Dhyp.set_extern_interp eval_tactic
-let _ = Dhyp.set_extern_intern_tac
- (fun t -> intern_tactic (make_empty_glob_sign()) t)