aboutsummaryrefslogtreecommitdiffhomepage
path: root/tactics/tacinterp.ml
diff options
context:
space:
mode:
Diffstat (limited to 'tactics/tacinterp.ml')
-rw-r--r--tactics/tacinterp.ml1371
1 files changed, 895 insertions, 476 deletions
diff --git a/tactics/tacinterp.ml b/tactics/tacinterp.ml
index c28e21e79..c77a18db4 100644
--- a/tactics/tacinterp.ml
+++ b/tactics/tacinterp.ml
@@ -16,6 +16,7 @@ open Entries
open Dyn
open Libobject
open Pattern
+open Matching
open Pp
open Rawterm
open Sign
@@ -68,7 +69,7 @@ type value =
| VTactic of loc * tactic (* For mixed ML/Ltac tactics (e.g. Tauto) *)
| VRTactic of (goal list sigma * validation) (* For Match results *)
(* Not a true value *)
- | VFun of (identifier * value) list * identifier option list *raw_tactic_expr
+ | VFun of (identifier*value) list * identifier option list * glob_tactic_expr
| VVoid
| VInteger of int
| VIdentifier of identifier (* idents which are not bound, as in "Intro H" *)
@@ -243,7 +244,7 @@ let coerce_to_inductive = function
(* Summary and Object declaration *)
let mactab = ref Gmap.empty
-let lookup qid = Gmap.find (locate_tactic qid) !mactab
+let lookup r = Gmap.find r !mactab
let _ =
let init () = mactab := Gmap.empty in
@@ -256,14 +257,34 @@ let _ =
Summary.survive_section = false }
(* Interpretation of extra generic arguments *)
-type genarg_interp_type =
- interp_sign -> goal sigma -> raw_generic_argument -> closed_generic_argument
-let extragenargtab = ref (Gmap.empty : (string,genarg_interp_type) Gmap.t)
-let add_genarg_interp id f = extragenargtab := Gmap.add id f !extragenargtab
-let lookup_genarg_interp id =
+type glob_sign = {
+ ltacvars : identifier list * identifier list;
+ (* ltac variables and the subset of vars introduced by Intro/Let/... *)
+ ltacrecvars : (identifier * ltac_constant) list;
+ (* ltac recursive names *)
+ metavars : int list;
+ (* metavariables introduced by patterns *)
+ gsigma : Evd.evar_map;
+ genv : Environ.env }
+
+type interp_genarg_type =
+ (glob_sign -> raw_generic_argument -> glob_generic_argument) *
+ (interp_sign -> goal sigma -> glob_generic_argument ->
+ closed_generic_argument) *
+ (Names.substitution -> glob_generic_argument -> glob_generic_argument)
+
+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 =
try Gmap.find id !extragenargtab
with Not_found -> failwith ("No interpretation function found for entry "^id)
+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
+
(* Unboxes VRec *)
let unrec = function
| VRec v -> !v
@@ -275,19 +296,34 @@ let unrec = function
(* We have identifier <| global_reference <| constr *)
-let find_ident id (lfun,_,_,env) =
- List.mem id lfun or
- List.mem id (ids_of_named_context (Environ.named_context env))
+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_recvar qid sign = List.assoc qid sign.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)
+
+(* a "ctxvar" is a var introduced by an intro tactic (Intro/LetTac/...) *)
+let find_ctxvar id sign = List.mem id (snd sign.ltacvars)
-(* Globalize a name which can be fresh *)
-let glob_ident l ist id =
+(* 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_hyp id sign =
+ List.mem id (ids_of_named_context (Environ.named_context sign.genv))
+
+(* Globalize a name introduced by Intro/LetTac/... ; it is allowed to *)
+(* be fresh in which case it is binding later on *)
+let intern_ident l ist id =
(* We use identifier both for variables and new names; thus nothing to do *)
- if find_ident id ist then () else l:=id::!l;
+ if find_ident id ist then () else l:=(id::fst !l,id::snd !l);
id
-let glob_name l ist = function
+let intern_name l ist = function
| Anonymous -> Anonymous
- | Name id -> Name (glob_ident l ist id)
+ | Name id -> Name (intern_ident l ist id)
let vars_of_ist (lfun,_,_,env) =
List.fold_left (fun s id -> Idset.add id s)
@@ -301,150 +337,187 @@ let get_current_context () =
let strict_check = ref false
(* Globalize a name which must be bound -- actually just check it is bound *)
-let glob_hyp ist (loc,id) =
+let intern_hyp ist (loc,id) =
let (_,env) = get_current_context () in
if (not !strict_check) or find_ident id ist then id
else
-(*
- try let _ = lookup (make_short_qualid id) in id
- with Not_found ->
-*)
Pretype_errors.error_var_not_found_loc loc id
-let glob_lochyp ist (_loc,_ as locid) = (loc,glob_hyp ist locid)
+let intern_lochyp ist (_loc,_ as locid) = (loc,intern_hyp ist locid)
let error_unbound_metanum loc n =
user_err_loc
- (loc,"glob_qualid_or_metanum", str "?" ++ int n ++ str " is unbound")
+ (loc,"intern_qualid_or_metanum", str "?" ++ int n ++ str " is unbound")
-let glob_metanum (_,lmeta,_,_) loc n =
- if List.mem n lmeta then n else error_unbound_metanum loc n
+let intern_metanum sign loc n =
+ if List.mem n sign.metavars then n else error_unbound_metanum loc n
-let glob_hyp_or_metanum ist = function
- | AN id -> AN (glob_hyp ist (loc,id))
- | MetaNum (_loc,n) -> MetaNum (loc,glob_metanum ist loc n)
+let intern_hyp_or_metanum ist = function
+ | AN id -> AN (intern_hyp ist (loc,id))
+ | MetaNum (_loc,n) -> MetaNum (loc,intern_metanum ist loc n)
-let glob_qualid_or_metanum ist = function
- | AN qid -> AN (Qualid(loc,
- shortest_qualid_of_global (vars_of_ist ist) (Nametab.global qid)))
- | MetaNum (_loc,n) -> MetaNum (loc,glob_metanum ist loc n)
+let intern_inductive ist = function
+ | Ident (loc,id) when find_var id ist -> ArgVar (loc,id)
+ | r -> ArgArg (Nametab.global_inductive r)
-let glob_reference ist = function
- | Ident (loc,id) as r when find_ident id ist -> r
- | r -> Qualid (loc,
- shortest_qualid_of_global (vars_of_ist ist) (Nametab.global r))
+let intern_or_metanum f ist = function
+ | AN x -> AN (f ist x)
+ | MetaNum (_loc,n) -> MetaNum (loc,intern_metanum ist loc n)
-let glob_ltac_qualid ist ref =
- let (loc,qid) = qualid_of_reference ref in
- try Qualid (loc,qualid_of_sp (locate_tactic qid))
- with Not_found -> glob_reference ist ref
+let intern_global_reference ist = function
+ | Ident (loc,id) as r when find_var id ist -> ArgVar (loc,id)
+ | r -> ArgArg (loc,Nametab.global r)
-let glob_ltac_reference strict ist = function
- | Ident (_loc,id) when not strict or find_ident id ist -> Ident (loc,id)
- | r -> glob_ltac_qualid ist r
+let intern_tac_ref ist = function
+ | Ident (loc,id) when find_ltacvar id ist -> ArgVar (loc,id)
+ | Ident (loc,id) ->
+ ArgArg
+ (try find_recvar id ist
+ with Not_found -> locate_tactic (make_short_qualid id))
+ | r ->
+ let (loc,qid) = qualid_of_reference r in
+ ArgArg (locate_tactic qid)
+
+let intern_tactic_reference ist r =
+ try intern_tac_ref ist r
+ with Not_found ->
+ let (loc,qid) = qualid_of_reference r in
+ error_global_not_found_loc loc qid
+
+let intern_constr_reference strict ist = function
+ | Ident (loc,id) as x when find_hyp id ist ->
+ RVar (loc,id), if strict then None else Some (CRef x)
+ | r ->
+ let loc,qid = qualid_of_reference r in
+ RRef (loc,Nametab.locate qid), (*Long names can't be Intro's names*) None
+
+let intern_reference strict ist r =
+ try Reference (intern_tac_ref ist r)
+ with Not_found ->
+ try ConstrMayEval (ConstrTerm (intern_constr_reference strict ist r))
+ with Not_found ->
+ match r with
+ | Ident (loc,id) when not strict -> Identifier id
+ | _ ->
+ let (loc,qid) = qualid_of_reference r in
+ error_global_not_found_loc loc qid
-let rec glob_intro_pattern lf ist = function
+let rec intern_intro_pattern lf ist = function
| IntroOrAndPattern l ->
- IntroOrAndPattern (List.map (List.map (glob_intro_pattern lf ist)) l)
+ IntroOrAndPattern (List.map (List.map (intern_intro_pattern lf ist)) l)
| IntroWildcard ->
IntroWildcard
| IntroIdentifier id ->
- IntroIdentifier (glob_ident lf ist id)
+ IntroIdentifier (intern_ident lf ist id)
-let glob_quantified_hypothesis ist x =
+let intern_quantified_hypothesis ist x =
(* We use identifier both for variables and quantified hyps (no way to
statically check the existence of a quantified hyp); thus nothing to do *)
x
-let glob_constr (lfun,_,sigma,env) c =
- let _ =
+let intern_constr {ltacvars=lfun; metavars=lmatch; gsigma=sigma; genv=env} c =
+ let c' =
Constrintern.for_grammar (Constrintern.interp_rawconstr_gen false
- sigma env [] false (lfun,[])) c
- in c
+ sigma env [] (Some lmatch) (fst lfun,[])) c
+ in (c',if !strict_check then None else Some c)
(* Globalize bindings *)
-let glob_binding ist (loc,b,c) =
- (loc,glob_quantified_hypothesis ist b,glob_constr ist c)
+let intern_binding ist (loc,b,c) =
+ (loc,intern_quantified_hypothesis ist b,intern_constr ist c)
-let glob_bindings ist = function
+let intern_bindings ist = function
| NoBindings -> NoBindings
- | ImplicitBindings l -> ImplicitBindings (List.map (glob_constr ist) l)
- | ExplicitBindings l -> ExplicitBindings (List.map (glob_binding ist) l)
+ | ImplicitBindings l -> ImplicitBindings (List.map (intern_constr ist) l)
+ | ExplicitBindings l -> ExplicitBindings (List.map (intern_binding ist) l)
-let glob_constr_with_bindings ist (c,bl) =
- (glob_constr ist c, glob_bindings ist bl)
+let intern_constr_with_bindings ist (c,bl) =
+ (intern_constr ist c, intern_bindings ist bl)
-let glob_clause_pattern ist (l,occl) =
+let intern_clause_pattern ist (l,occl) =
let rec check = function
| (hyp,l) :: rest ->
let (_loc,_ as id) = skip_metaid hyp in
- (AI(loc,glob_hyp ist id),l)::(check rest)
+ ((loc,intern_hyp ist id),l)::(check rest)
| [] -> []
in (l,check occl)
-let glob_induction_arg ist = function
- | ElimOnConstr c -> ElimOnConstr (glob_constr ist c)
+let intern_induction_arg ist = function
+ | ElimOnConstr c -> ElimOnConstr (intern_constr ist c)
| ElimOnAnonHyp n as x -> x
| ElimOnIdent (_loc,id) as x -> ElimOnIdent (loc,id)
(* Globalizes a reduction expression *)
-let glob_evaluable_or_metanum ist = function
- | AN qid -> AN (glob_reference ist qid)
- | MetaNum (_loc,n) -> MetaNum (loc,glob_metanum ist loc n)
-
-let glob_unfold ist (l,qid) = (l,glob_evaluable_or_metanum ist qid)
-
-let glob_flag ist red =
- { red with rConst = List.map (glob_evaluable_or_metanum ist) red.rConst }
-
-let glob_constr_occurrence ist (l,c) = (l,glob_constr ist c)
-
-let glob_redexp ist = function
- | Unfold l -> Unfold (List.map (glob_unfold ist) l)
- | Fold l -> Fold (List.map (glob_constr ist) l)
- | Cbv f -> Cbv (glob_flag ist f)
- | Lazy f -> Lazy (glob_flag ist f)
- | Pattern l -> Pattern (List.map (glob_constr_occurrence ist) l)
- | Simpl o -> Simpl (option_app (glob_constr_occurrence ist) o)
+let intern_evaluable_or_metanum ist = function
+ | AN qid ->
+ let e = match qid with
+ | Ident (loc,id) when find_ctxvar id ist ->
+ ArgArg (EvalVarRef id, Some id)
+ | Ident (loc,id) as r when find_var id ist -> ArgVar (loc,id)
+ | r ->
+ let e = match fst (intern_constr_reference true ist r) with
+ | RRef (_,ConstRef c) -> EvalConstRef c
+ | RRef (_,VarRef c) | RVar (_,c) -> EvalVarRef c
+ | _ -> error_not_evaluable (pr_reference r) in
+ let short_name = match r with
+ | Ident (_,id) when not !strict_check -> Some id
+ | _ -> None in
+ ArgArg (e,short_name)
+ in AN e
+ | MetaNum (_loc,n) -> MetaNum (loc,intern_metanum ist loc n)
+
+let intern_unfold ist (l,qid) = (l,intern_evaluable_or_metanum ist qid)
+
+let intern_flag ist red =
+ { red with rConst = List.map (intern_evaluable_or_metanum ist) red.rConst }
+
+let intern_constr_occurrence ist (l,c) = (l,intern_constr ist c)
+
+let intern_redexp 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_occurrence ist) l)
+ | Simpl o -> Simpl (option_app (intern_constr_occurrence ist) o)
| (Red _ | Hnf as r) -> r
- | ExtraRedExpr (s,c) -> ExtraRedExpr (s, glob_constr ist c)
+ | ExtraRedExpr (s,c) -> ExtraRedExpr (s, intern_constr ist c)
(* Interprets an hypothesis name *)
-let glob_hyp_location ist = function
+let intern_hyp_location ist = function
| InHyp id ->
let (_loc,_ as id) = skip_metaid id in
- InHyp (AI(loc,glob_hyp ist id))
+ InHyp (loc,intern_hyp ist id)
| InHypType id ->
let (_loc,_ as id) = skip_metaid id in
- InHypType (AI(loc,glob_hyp ist id))
+ InHypType (loc,intern_hyp ist id)
(* Reads a pattern *)
-let glob_pattern evc env lfun = function
+let intern_pattern evc env lfun = function
| Subterm (ido,pc) ->
let lfun = List.map (fun id -> (id, mkVar id)) lfun in
- let (metas,_) = interp_constrpattern_gen evc env (lfun,[]) pc in
- metas, Subterm (ido,pc)
+ let (metas,pat) = interp_constrpattern_gen evc env (lfun,[]) pc in
+ metas, Subterm (ido,pat)
| Term pc ->
let lfun = List.map (fun id -> (id, mkVar id)) lfun in
- let (metas,_) = interp_constrpattern_gen evc env (lfun,[]) pc in
- metas, Term pc
+ let (metas,pat) = interp_constrpattern_gen evc env (lfun,[]) pc in
+ metas, Term pat
-let glob_constr_may_eval ist = function
- | ConstrEval (r,c) -> ConstrEval (glob_redexp ist r,glob_constr ist c)
+let intern_constr_may_eval ist = function
+ | ConstrEval (r,c) -> ConstrEval (intern_redexp ist r,intern_constr ist c)
| ConstrContext (locid,c) ->
- ConstrContext ((loc,glob_hyp ist locid),glob_constr ist c)
- | ConstrTypeOf c -> ConstrTypeOf (glob_constr ist c)
- | ConstrTerm c -> ConstrTerm (glob_constr ist c)
+ ConstrContext ((loc,intern_hyp ist locid),intern_constr ist c)
+ | ConstrTypeOf c -> ConstrTypeOf (intern_constr ist c)
+ | ConstrTerm c -> ConstrTerm (intern_constr ist c)
(* Reads the hypotheses of a Match Context rule *)
-let rec glob_match_context_hyps evc env lfun = function
+let rec intern_match_context_hyps evc env lfun = function
| (NoHypId mp)::tl ->
- let metas1, pat = glob_pattern evc env lfun mp in
- let lfun, metas2, hyps = glob_match_context_hyps evc env lfun tl in
+ let metas1, pat = intern_pattern evc env lfun mp in
+ let lfun, metas2, hyps = intern_match_context_hyps evc env lfun tl in
lfun, metas1@metas2, (NoHypId pat)::hyps
| (Hyp ((_,s) as locs,mp))::tl ->
- let metas1, pat = glob_pattern evc env lfun mp in
- let lfun, metas2, hyps = glob_match_context_hyps evc env lfun tl in
+ let metas1, pat = intern_pattern evc env lfun mp in
+ let lfun, metas2, hyps = intern_match_context_hyps evc env lfun tl in
s::lfun, metas1@metas2, Hyp (locs,pat)::hyps
| [] -> lfun, [], []
@@ -459,7 +532,7 @@ let extract_names lrc =
(fun ((loc,name),_) l ->
if List.mem name l then
user_err_loc
- (loc, "glob_tactic", str "This variable is bound several times");
+ (loc, "intern_tactic", str "This variable is bound several times");
name::l)
lrc []
@@ -472,236 +545,244 @@ let extract_let_names lrc =
name::l)
lrc []
-(* Globalizes tactics *)
-let rec glob_atomic lf (_,_,_,_ as ist) = function
+(* Globalizes tactics : raw_tactic_expr -> glob_tactic_expr *)
+let rec intern_atomic lf ist x =
+ match (x:raw_atomic_tactic_expr) with
(* Basic tactics *)
| TacIntroPattern l ->
- TacIntroPattern (List.map (glob_intro_pattern lf ist) l)
- | TacIntrosUntil hyp -> TacIntrosUntil (glob_quantified_hypothesis ist hyp)
+ TacIntroPattern (List.map (intern_intro_pattern lf ist) l)
+ | TacIntrosUntil hyp -> TacIntrosUntil (intern_quantified_hypothesis ist hyp)
| TacIntroMove (ido,ido') ->
- TacIntroMove (option_app (glob_ident lf ist) ido,
- option_app (fun (_loc,_ as x) -> (loc,glob_hyp ist x)) ido')
+ TacIntroMove (option_app (intern_ident lf ist) ido,
+ option_app (fun (_loc,_ as x) -> (loc,intern_hyp ist x)) ido')
| TacAssumption -> TacAssumption
- | TacExact c -> TacExact (glob_constr ist c)
- | TacApply cb -> TacApply (glob_constr_with_bindings ist cb)
+ | TacExact c -> TacExact (intern_constr ist c)
+ | TacApply cb -> TacApply (intern_constr_with_bindings ist cb)
| TacElim (cb,cbo) ->
- TacElim (glob_constr_with_bindings ist cb,
- option_app (glob_constr_with_bindings ist) cbo)
- | TacElimType c -> TacElimType (glob_constr ist c)
- | TacCase cb -> TacCase (glob_constr_with_bindings ist cb)
- | TacCaseType c -> TacCaseType (glob_constr ist c)
- | TacFix (idopt,n) -> TacFix (option_app (glob_ident lf ist) idopt,n)
+ TacElim (intern_constr_with_bindings ist cb,
+ option_app (intern_constr_with_bindings ist) cbo)
+ | TacElimType c -> TacElimType (intern_constr ist c)
+ | TacCase cb -> TacCase (intern_constr_with_bindings ist cb)
+ | TacCaseType c -> TacCaseType (intern_constr ist c)
+ | TacFix (idopt,n) -> TacFix (option_app (intern_ident lf ist) idopt,n)
| TacMutualFix (id,n,l) ->
- let f (id,n,c) = (glob_ident lf ist id,n,glob_constr ist c) in
- TacMutualFix (glob_ident lf ist id, n, List.map f l)
- | TacCofix idopt -> TacCofix (option_app (glob_ident lf ist) idopt)
+ let f (id,n,c) = (intern_ident lf ist id,n,intern_constr ist c) in
+ TacMutualFix (intern_ident lf ist id, n, List.map f l)
+ | TacCofix idopt -> TacCofix (option_app (intern_ident lf ist) idopt)
| TacMutualCofix (id,l) ->
- let f (id,c) = (glob_ident lf ist id,glob_constr ist c) in
- TacMutualCofix (glob_ident lf ist id, List.map f l)
- | TacCut c -> TacCut (glob_constr ist c)
+ let f (id,c) = (intern_ident lf ist id,intern_constr ist c) in
+ TacMutualCofix (intern_ident lf ist id, List.map f l)
+ | TacCut c -> TacCut (intern_constr ist c)
| TacTrueCut (ido,c) ->
- TacTrueCut (option_app (glob_ident lf ist) ido, glob_constr ist c)
- | TacForward (b,na,c) -> TacForward (b,glob_name lf ist na,glob_constr ist c)
- | TacGeneralize cl -> TacGeneralize (List.map (glob_constr ist) cl)
- | TacGeneralizeDep c -> TacGeneralizeDep (glob_constr ist c)
+ TacTrueCut (option_app (intern_ident lf ist) ido, intern_constr ist c)
+ | TacForward (b,na,c) -> TacForward (b,intern_name lf ist na,intern_constr ist c)
+ | TacGeneralize cl -> TacGeneralize (List.map (intern_constr ist) cl)
+ | TacGeneralizeDep c -> TacGeneralizeDep (intern_constr ist c)
| TacLetTac (id,c,clp) ->
- TacLetTac (id,glob_constr ist c,glob_clause_pattern ist clp)
- | TacInstantiate (n,c) -> TacInstantiate (n,glob_constr ist c)
+ let id = intern_ident lf ist id in
+ TacLetTac (id,intern_constr ist c,intern_clause_pattern ist clp)
+ | TacInstantiate (n,c) -> TacInstantiate (n,intern_constr ist c)
(* Automation tactics *)
| TacTrivial l -> TacTrivial l
| TacAuto (n,l) -> TacAuto (n,l)
| TacAutoTDB n -> TacAutoTDB n
| TacDestructHyp (b,(_loc,_ as id)) ->
- TacDestructHyp(b,(loc,glob_hyp ist id))
+ TacDestructHyp(b,(loc,intern_hyp ist id))
| TacDestructConcl -> TacDestructConcl
| TacSuperAuto (n,l,b1,b2) -> TacSuperAuto (n,l,b1,b2)
| TacDAuto (n,p) -> TacDAuto (n,p)
(* Derived basic tactics *)
- | TacOldInduction h -> TacOldInduction (glob_quantified_hypothesis ist h)
+ | TacOldInduction h -> TacOldInduction (intern_quantified_hypothesis ist h)
| TacNewInduction (c,cbo,ids) ->
- TacNewInduction (glob_induction_arg ist c,
- option_app (glob_constr_with_bindings ist) cbo,
- List.map (List.map (glob_ident lf ist)) ids)
- | TacOldDestruct h -> TacOldDestruct (glob_quantified_hypothesis ist h)
+ TacNewInduction (intern_induction_arg ist c,
+ option_app (intern_constr_with_bindings ist) cbo,
+ List.map (List.map (intern_ident lf ist)) ids)
+ | TacOldDestruct h -> TacOldDestruct (intern_quantified_hypothesis ist h)
| TacNewDestruct (c,cbo,ids) ->
- TacNewDestruct (glob_induction_arg ist c,
- option_app (glob_constr_with_bindings ist) cbo,
- List.map (List.map (glob_ident lf ist)) ids)
+ TacNewDestruct (intern_induction_arg ist c,
+ option_app (intern_constr_with_bindings ist) cbo,
+ List.map (List.map (intern_ident lf ist)) ids)
| TacDoubleInduction (h1,h2) ->
- let h1 = glob_quantified_hypothesis ist h1 in
- let h2 = glob_quantified_hypothesis ist h2 in
+ let h1 = intern_quantified_hypothesis ist h1 in
+ let h2 = intern_quantified_hypothesis ist h2 in
TacDoubleInduction (h1,h2)
- | TacDecomposeAnd c -> TacDecomposeAnd (glob_constr ist c)
- | TacDecomposeOr c -> TacDecomposeOr (glob_constr ist c)
+ | TacDecomposeAnd c -> TacDecomposeAnd (intern_constr ist c)
+ | TacDecomposeOr c -> TacDecomposeOr (intern_constr ist c)
| TacDecompose (l,c) ->
- let l = List.map (glob_qualid_or_metanum ist) l in
- TacDecompose (l,glob_constr ist c)
- | TacSpecialize (n,l) -> TacSpecialize (n,glob_constr_with_bindings ist l)
- | TacLApply c -> TacLApply (glob_constr ist c)
+ let l = List.map (intern_or_metanum intern_inductive ist) l in
+ TacDecompose (l,intern_constr ist c)
+ | TacSpecialize (n,l) -> TacSpecialize (n,intern_constr_with_bindings ist l)
+ | TacLApply c -> TacLApply (intern_constr ist c)
(* Context management *)
- | TacClear l -> TacClear (List.map (glob_hyp_or_metanum ist) l)
- | TacClearBody l -> TacClearBody (List.map (glob_hyp_or_metanum ist) l)
+ | TacClear l -> TacClear (List.map (intern_hyp_or_metanum ist) l)
+ | TacClearBody l -> TacClearBody (List.map (intern_hyp_or_metanum ist) l)
| TacMove (dep,id1,id2) ->
- TacMove (dep,glob_lochyp ist id1,glob_lochyp ist id2)
- | TacRename (id1,id2) -> TacRename (glob_lochyp ist id1, glob_lochyp ist id2)
+ TacMove (dep,intern_lochyp ist id1,intern_lochyp ist id2)
+ | TacRename (id1,id2) -> TacRename (intern_lochyp ist id1, intern_lochyp ist id2)
(* Constructors *)
- | TacLeft bl -> TacLeft (glob_bindings ist bl)
- | TacRight bl -> TacRight (glob_bindings ist bl)
- | TacSplit (b,bl) -> TacSplit (b,glob_bindings ist bl)
- | TacAnyConstructor t -> TacAnyConstructor (option_app (glob_tactic ist) t)
- | TacConstructor (n,bl) -> TacConstructor (n, glob_bindings ist bl)
+ | TacLeft bl -> TacLeft (intern_bindings ist bl)
+ | TacRight bl -> TacRight (intern_bindings ist bl)
+ | TacSplit (b,bl) -> TacSplit (b,intern_bindings ist bl)
+ | TacAnyConstructor t -> TacAnyConstructor (option_app (intern_tactic ist) t)
+ | TacConstructor (n,bl) -> TacConstructor (n, intern_bindings ist bl)
(* Conversion *)
| TacReduce (r,cl) ->
- TacReduce (glob_redexp ist r, List.map (glob_hyp_location ist) cl)
+ TacReduce (intern_redexp ist r, List.map (intern_hyp_location ist) cl)
| TacChange (occl,c,cl) ->
- TacChange (option_app (glob_constr_occurrence ist) occl,
- glob_constr ist c, List.map (glob_hyp_location ist) cl)
+ TacChange (option_app (intern_constr_occurrence ist) occl,
+ intern_constr ist c, List.map (intern_hyp_location ist) cl)
(* Equivalence relations *)
| TacReflexivity -> TacReflexivity
| TacSymmetry -> TacSymmetry
- | TacTransitivity c -> TacTransitivity (glob_constr ist c)
+ | TacTransitivity c -> TacTransitivity (intern_constr ist c)
(* For extensions *)
| TacExtend (_loc,opn,l) ->
let _ = lookup_tactic opn in
- TacExtend (loc,opn,List.map (glob_genarg ist) l)
- | TacAlias (_,l,body) as t ->
- (* failwith "TacAlias globalisation: TODO" *)
- t
+ TacExtend (loc,opn,List.map (intern_genarg ist) l)
+ | TacAlias (s,l,body) ->
+ TacAlias (s,List.map (fun (id,a) -> (id,intern_genarg ist a)) l,intern_tactic ist body)
-and glob_tactic ist tac = snd (glob_tactic_seq ist tac)
+and intern_tactic ist tac = (snd (intern_tactic_seq ist tac) : glob_tactic_expr)
-and glob_tactic_seq (lfun,lmeta,sigma,env as ist) = function
+and intern_tactic_seq ist = function
| TacAtom (_loc,t) ->
- let lf = ref lfun in
- let t = glob_atomic lf ist t in
+ let lf = ref ist.ltacvars in
+ let t = intern_atomic lf ist t in
!lf, TacAtom (loc, t)
- | TacFun tacfun -> lfun, TacFun (glob_tactic_fun ist tacfun)
+ | TacFun tacfun -> ist.ltacvars, TacFun (intern_tactic_fun ist tacfun)
| TacLetRecIn (lrc,u) ->
let names = extract_names lrc in
- let ist = (names@lfun,lmeta,sigma,env) in
- let lrc = List.map (fun (n,b) -> (n,glob_tactic_fun ist b)) lrc in
- lfun, TacLetRecIn (lrc,glob_tactic ist u)
+ let (l1,l2) = ist.ltacvars in
+ let ist = { ist with ltacvars = (names@l1,l2) } in
+ let lrc = List.map (fun (n,b) -> (n,intern_tactic_fun ist b)) lrc in
+ ist.ltacvars, TacLetRecIn (lrc,intern_tactic ist u)
| TacLetIn (l,u) ->
- let l = List.map (fun (n,c,b) -> (n,option_app (glob_constr_may_eval ist)
- c,glob_tacarg !strict_check ist b)) l in
- let ist' = ((extract_let_names l)@lfun,lmeta,sigma,env) in
- lfun, TacLetIn (l,glob_tactic ist' u)
+ let l = List.map
+ (fun (n,c,b) ->
+ (n,option_app (intern_constr_may_eval ist) c, intern_tacarg !strict_check ist b)) l in
+ let (l1,l2) = ist.ltacvars in
+ let ist' = { ist with ltacvars = ((extract_let_names l)@l1,l2) } in
+ ist.ltacvars, TacLetIn (l,intern_tactic ist' u)
| TacLetCut l ->
- let f (n,c,t) = (n,glob_constr_may_eval ist c,glob_tacarg !strict_check
- ist t) in
- lfun, TacLetCut (List.map f l)
+ let f (n,c,t) = (n,intern_constr_may_eval ist c,intern_tacarg !strict_check ist t) in
+ ist.ltacvars, TacLetCut (List.map f l)
| TacMatchContext (lr,lmr) ->
- lfun, TacMatchContext(lr, glob_match_rule ist lmr)
+ ist.ltacvars, TacMatchContext(lr, intern_match_rule ist lmr)
| TacMatch (c,lmr) ->
- lfun, TacMatch (glob_constr_may_eval ist c,glob_match_rule ist lmr)
- | TacId -> lfun, TacId
- | TacFail _ as x -> lfun, x
- | TacProgress tac -> lfun, TacProgress (glob_tactic ist tac)
- | TacAbstract (tac,s) -> lfun, TacAbstract (glob_tactic ist tac,s)
+ ist.ltacvars, TacMatch (intern_constr_may_eval ist c,intern_match_rule ist lmr)
+ | TacId -> ist.ltacvars, TacId
+ | TacFail _ as x -> ist.ltacvars, x
+ | TacProgress tac -> ist.ltacvars, TacProgress (intern_tactic ist tac)
+ | TacAbstract (tac,s) -> ist.ltacvars, TacAbstract (intern_tactic ist tac,s)
| TacThen (t1,t2) ->
- let lfun', t1 = glob_tactic_seq ist t1 in
- let lfun'', t2 = glob_tactic_seq (lfun',lmeta,sigma,env) t2 in
+ let lfun', t1 = intern_tactic_seq ist t1 in
+ let lfun'', t2 = intern_tactic_seq { ist with ltacvars = lfun' } t2 in
lfun'', TacThen (t1,t2)
| TacThens (t,tl) ->
- let lfun', t = glob_tactic_seq ist t in
+ let lfun', t = intern_tactic_seq ist t in
(* Que faire en cas de (tac complexe avec Match et Thens; tac2) ?? *)
- lfun', TacThens (t, List.map (glob_tactic (lfun',lmeta,sigma,env)) tl)
- | TacDo (n,tac) -> lfun, TacDo (n,glob_tactic ist tac)
- | TacTry tac -> lfun, TacTry (glob_tactic ist tac)
- | TacInfo tac -> lfun, TacInfo (glob_tactic ist tac)
- | TacRepeat tac -> lfun, TacRepeat (glob_tactic ist tac)
+ lfun',
+ TacThens (t, List.map (intern_tactic { ist with ltacvars = lfun' }) tl)
+ | TacDo (n,tac) -> ist.ltacvars, TacDo (n,intern_tactic ist tac)
+ | TacTry tac -> ist.ltacvars, TacTry (intern_tactic ist tac)
+ | TacInfo tac -> ist.ltacvars, TacInfo (intern_tactic ist tac)
+ | TacRepeat tac -> ist.ltacvars, TacRepeat (intern_tactic ist tac)
| TacOrelse (tac1,tac2) ->
- lfun, TacOrelse (glob_tactic ist tac1,glob_tactic ist tac2)
- | TacFirst l -> lfun, TacFirst (List.map (glob_tactic ist) l)
- | TacSolve l -> lfun, TacSolve (List.map (glob_tactic ist) l)
- | TacArg a -> lfun, TacArg (glob_tacarg true ist a)
+ ist.ltacvars, TacOrelse (intern_tactic ist tac1,intern_tactic ist tac2)
+ | TacFirst l -> ist.ltacvars, TacFirst (List.map (intern_tactic ist) l)
+ | TacSolve l -> ist.ltacvars, TacSolve (List.map (intern_tactic ist) l)
+ | TacArg a -> ist.ltacvars, TacArg (intern_tacarg true ist a)
-and glob_tactic_fun (lfun,lmeta,sigma,env) (var,body) =
- let lfun' = List.rev_append (filter_some var) lfun in
- (var,glob_tactic (lfun',lmeta,sigma,env) body)
+and intern_tactic_fun ist (var,body) =
+ let (l1,l2) = ist.ltacvars in
+ let lfun' = List.rev_append (filter_some var) l1 in
+ (var,intern_tactic { ist with ltacvars = (lfun',l2) } body)
-and glob_tacarg strict ist = function
+and intern_tacarg strict ist = function
| TacVoid -> TacVoid
- | Reference r -> Reference (glob_ltac_reference strict ist r)
+ | Reference r -> intern_reference strict ist r
+ | Identifier id -> anomaly "Not used only in raw_tactic_expr"
| Integer n -> Integer n
- | ConstrMayEval c -> ConstrMayEval (glob_constr_may_eval ist c)
- | MetaNumArg (_loc,n) -> MetaNumArg (loc,glob_metanum ist loc n)
+ | ConstrMayEval c -> ConstrMayEval (intern_constr_may_eval ist c)
| MetaIdArg (_loc,_) -> error_syntactic_metavariables_not_allowed loc
| TacCall (_loc,f,l) ->
TacCall (_loc,
- glob_ltac_reference strict ist f,
- List.map (glob_tacarg !strict_check ist) l)
- | Tacexp t -> Tacexp (glob_tactic ist t)
+ intern_tactic_reference ist f,
+ List.map (intern_tacarg !strict_check ist) l)
+ | Tacexp t -> Tacexp (intern_tactic ist t)
| TacDynamic(_,t) as x ->
(match tag t with
- | "tactic"|"value"|"constr" -> x
- | s -> anomaly_loc (loc, "Tacinterp.val_interp",
+ | "tactic" | "value" | "constr" -> x
+ | s -> anomaly_loc (loc, "",
str "Unknown dynamic: <" ++ str s ++ str ">"))
(* Reads the rules of a Match Context or a Match *)
-and glob_match_rule (lfun,lmeta,sigma,env as ist) = function
+and intern_match_rule ist = function
| (All tc)::tl ->
- (All (glob_tactic ist tc))::(glob_match_rule ist tl)
+ All (intern_tactic ist tc) :: (intern_match_rule ist tl)
| (Pat (rl,mp,tc))::tl ->
- let lfun',metas1,hyps = glob_match_context_hyps Evd.empty env lfun rl in
- let metas2,pat = glob_pattern Evd.empty env lfun mp in
+ let {ltacvars=(lfun,l2); metavars=lmeta; gsigma=sigma; genv=env} = ist in
+ let lfun',metas1,hyps = intern_match_context_hyps sigma env lfun rl in
+ let metas2,pat = intern_pattern sigma env lfun mp in
let metas = list_uniquize (metas1@metas2@lmeta) in
- (Pat (hyps,pat,glob_tactic (lfun',metas,sigma,env) tc))
- ::(glob_match_rule ist tl)
+ let ist' = { ist with ltacvars = (lfun',l2); metavars = metas } in
+ Pat (hyps,pat,intern_tactic ist' tc) :: (intern_match_rule ist tl)
| [] -> []
-and glob_genarg ist x =
+and intern_genarg ist x =
match genarg_tag x with
- | BoolArgType -> in_gen rawwit_bool (out_gen rawwit_bool x)
- | IntArgType -> in_gen rawwit_int (out_gen rawwit_int x)
+ | BoolArgType -> in_gen globwit_bool (out_gen rawwit_bool x)
+ | IntArgType -> in_gen globwit_int (out_gen rawwit_int x)
| IntOrVarArgType ->
let f = function
- | ArgVar (_loc,id) -> ArgVar (loc,glob_hyp ist (loc,id))
+ | ArgVar (_loc,id) -> ArgVar (loc,intern_hyp ist (loc,id))
| ArgArg n as x -> x in
- in_gen rawwit_int_or_var (f (out_gen rawwit_int_or_var x))
+ in_gen globwit_int_or_var (f (out_gen rawwit_int_or_var x))
| StringArgType ->
- in_gen rawwit_string (out_gen rawwit_string x)
+ in_gen globwit_string (out_gen rawwit_string x)
| PreIdentArgType ->
- in_gen rawwit_pre_ident (out_gen rawwit_pre_ident x)
+ in_gen globwit_pre_ident (out_gen rawwit_pre_ident x)
| IdentArgType ->
- in_gen rawwit_ident (glob_hyp ist (dummy_loc,out_gen rawwit_ident x))
+ in_gen globwit_ident (intern_hyp ist (dummy_loc,out_gen rawwit_ident x))
| RefArgType ->
- in_gen rawwit_ref (glob_ltac_reference !strict_check ist
- (out_gen rawwit_ref x))
+ in_gen globwit_ref (intern_global_reference ist (out_gen rawwit_ref x))
| SortArgType ->
- in_gen rawwit_sort (out_gen rawwit_sort x)
+ in_gen globwit_sort (out_gen rawwit_sort x)
| ConstrArgType ->
- in_gen rawwit_constr (glob_constr ist (out_gen rawwit_constr x))
+ in_gen globwit_constr (intern_constr ist (out_gen rawwit_constr x))
| ConstrMayEvalArgType ->
- in_gen rawwit_constr_may_eval (glob_constr_may_eval ist
- (out_gen rawwit_constr_may_eval x))
+ in_gen globwit_constr_may_eval
+ (intern_constr_may_eval ist (out_gen rawwit_constr_may_eval x))
| QuantHypArgType ->
- in_gen rawwit_quant_hyp
- (glob_quantified_hypothesis ist (out_gen rawwit_quant_hyp x))
+ in_gen globwit_quant_hyp
+ (intern_quantified_hypothesis ist (out_gen rawwit_quant_hyp x))
| RedExprArgType ->
- in_gen rawwit_red_expr (glob_redexp ist (out_gen rawwit_red_expr x))
+ in_gen globwit_red_expr (intern_redexp ist (out_gen rawwit_red_expr x))
| TacticArgType ->
- in_gen rawwit_tactic (glob_tactic ist (out_gen rawwit_tactic x))
+ in_gen globwit_tactic (intern_tactic ist (out_gen rawwit_tactic x))
| CastedOpenConstrArgType ->
- in_gen rawwit_casted_open_constr
- (glob_constr ist (out_gen rawwit_casted_open_constr x))
+ in_gen globwit_casted_open_constr
+ (intern_constr ist (out_gen rawwit_casted_open_constr x))
| ConstrWithBindingsArgType ->
- in_gen rawwit_constr_with_bindings
- (glob_constr_with_bindings ist (out_gen rawwit_constr_with_bindings x))
- | List0ArgType _ -> app_list0 (glob_genarg ist) x
- | List1ArgType _ -> app_list1 (glob_genarg ist) x
- | OptArgType _ -> app_opt (glob_genarg ist) x
- | PairArgType _ -> app_pair (glob_genarg ist) (glob_genarg ist) x
- | ExtraArgType s -> x
+ in_gen globwit_constr_with_bindings
+ (intern_constr_with_bindings ist (out_gen rawwit_constr_with_bindings x))
+ | List0ArgType _ -> app_list0 (intern_genarg ist) x
+ | List1ArgType _ -> app_list1 (intern_genarg ist) x
+ | OptArgType _ -> app_opt (intern_genarg ist) x
+ | PairArgType _ -> app_pair (intern_genarg ist) (intern_genarg ist) x
+ | ExtraArgType s -> lookup_genarg_glob s ist x
-(**** End Globalization ****)
+(************* End globalization ************)
+
+(***************************************************************************)
+(* Evaluation/interpretation *)
(* Associates variables with values and gives the remaining variables and
values *)
@@ -722,12 +803,14 @@ let give_context ctxt = function
| None -> []
| Some id -> [id,VConstr_context ctxt]
-(* Reads a pattern *)
+(* Reads a pattern by substituing vars of lfun *)
+let eval_pattern lfun c =
+ let lvar = List.map (fun (id,c) -> (id,pattern_of_constr c)) lfun in
+ instantiate_pattern lvar c
+
let read_pattern evc env lfun = function
- | Subterm (ido,pc) ->
- Subterm (ido,snd (interp_constrpattern_gen evc env lfun pc))
- | Term pc ->
- Term (snd (interp_constrpattern_gen evc env lfun pc))
+ | Subterm (ido,pc) -> Subterm (ido,eval_pattern lfun pc)
+ | Term pc -> Term (eval_pattern lfun pc)
(* Reads the hypotheses of a Match Context rule *)
let rec read_match_context_hyps evc env lfun lidh = function
@@ -748,8 +831,8 @@ let rec read_match_context_hyps evc env lfun lidh = function
let rec read_match_rule evc env lfun = function
| (All tc)::tl -> (All tc)::(read_match_rule evc env lfun tl)
| (Pat (rl,mp,tc))::tl ->
- (Pat (read_match_context_hyps evc env lfun [] rl,
- read_pattern evc env lfun mp,tc))
+ Pat (read_match_context_hyps evc env lfun [] rl,
+ read_pattern evc env lfun mp,tc)
::(read_match_rule evc env lfun tl)
| [] -> []
@@ -778,7 +861,7 @@ let rec verify_metas_coherence gl lcm = function
(* Tries to match a pattern and a constr *)
let apply_matching pat csr =
try
- (Pattern.matches pat csr)
+ (matches pat csr)
with
PatternMatchingFailure -> raise No_match
@@ -799,7 +882,7 @@ let apply_one_mhyp_context ist env gl lmatch mhyp lhyps noccopt =
| Term t ->
(try
let lmeta =
- verify_metas_coherence gl lmatch (Pattern.matches t hyp) in
+ verify_metas_coherence gl lmatch (matches t hyp) in
(get_id_couple id mhyp,[],lmeta,tl,(id,hyp),None)
with | PatternMatchingFailure | Not_coherent_metas ->
apply_one_mhyp_context_rec ist env mhyp (lhyps_acc@[id,hyp]) 0 tl)
@@ -855,8 +938,7 @@ let constr_to_qid loc c =
let check_clause_pattern ist gl (l,occl) =
let sign = pf_hyps gl in
let rec check acc = function
- | (hyp,l) :: rest ->
- let _,hyp = skip_metaid hyp in
+ | ((_,hyp),l) :: rest ->
if List.mem hyp acc then
error ("Hypothesis "^(string_of_id hyp)^" occurs twice");
if not (mem_named_context hyp sign) then
@@ -927,13 +1009,13 @@ let eval_variable ist gl (loc,id) =
else
user_err_loc (loc,"eval_variable",pr_id id ++ str " not found")
-let hyp_interp = eval_variable
+let interp_hyp = eval_variable
let eval_name ist = function
| Anonymous -> Anonymous
| Name id -> Name (eval_ident ist id)
-let hyp_or_metanum_interp ist gl = function
+let interp_hyp_or_metanum ist gl = function
| AN id -> eval_variable ist gl (dummy_loc,id)
| MetaNum (loc,n) -> constr_to_id loc (List.assoc n ist.lmatch)
@@ -954,33 +1036,38 @@ let eval_ref ist env = function
try unrec (List.assoc id ist.lfun)
with Not_found -> interp_pure_qualid false env (loc,make_short_qualid id)
-let reference_interp ist env qid =
- let v = eval_ref ist env qid in
- coerce_to_reference env v
-
-let pf_reference_interp ist gl = reference_interp ist (pf_env gl)
-
-(* Interprets a qualified name. This can be a metavariable to be injected *)
-let qualid_or_metanum_interp ist = function
- | AN qid -> qid
- | MetaNum (loc,n) -> constr_to_qid loc (List.assoc n ist.lmatch)
-
-let eval_ref_or_metanum ist gl = function
- | AN qid -> eval_ref ist gl qid
- | MetaNum (loc,n) -> VConstr (List.assoc n ist.lmatch)
-
-let interp_evaluable_or_metanum ist env c =
- let c = eval_ref_or_metanum ist env c in
- coerce_to_evaluable_ref env c
-
-let interp_inductive_or_metanum ist gl c =
- let c = eval_ref_or_metanum ist (pf_env gl) c in
- coerce_to_inductive c
+let interp_reference ist env = function
+ | ArgArg (_,r) -> r
+ | ArgVar (loc,id) -> coerce_to_reference env (unrec (List.assoc id ist.lfun))
+
+let pf_interp_reference ist gl = interp_reference ist (pf_env gl)
+
+let interp_inductive_or_metanum ist = function
+ | MetaNum (loc,n) ->
+ coerce_to_inductive (VConstr (List.assoc n ist.lmatch))
+ | AN r -> match r with
+ | ArgArg r -> r
+ | ArgVar (_,id) ->
+ coerce_to_inductive (unrec (List.assoc id ist.lfun))
+
+let interp_evaluable_or_metanum ist env = function
+ | MetaNum (loc,n) ->
+ coerce_to_evaluable_ref env (VConstr (List.assoc n ist.lmatch))
+ | AN r -> match r with
+ | ArgArg (r,Some id) ->
+ (* 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)
+ with Not_found -> r)
+ | ArgArg (r,None) -> r
+ | ArgVar (_,id) ->
+ coerce_to_evaluable_ref env (unrec (List.assoc id ist.lfun))
(* Interprets an hypothesis name *)
let interp_hyp_location ist gl = function
- | InHyp id -> InHyp (hyp_interp ist gl (skip_metaid id))
- | InHypType id -> InHypType (hyp_interp ist gl (skip_metaid id))
+ | InHyp id -> InHyp (interp_hyp ist gl id)
+ | InHypType id -> InHypType (interp_hyp ist gl id)
let eval_opt_ident ist = option_app (eval_ident ist)
@@ -997,57 +1084,74 @@ let rec constr_list_aux env = function
let constr_list ist env = constr_list_aux env ist.lfun
-let interp_constr ocl ist sigma env c =
- interp_constr_gen sigma env (constr_list ist env) ist.lmatch c ocl
+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 []
+
+let interp_casted_constr ocl ist sigma env (c,ce) =
+ let (l1,l2) = constr_list ist env in
+ let rtype lst = retype_list sigma env lst in
+ let csr =
+ match ce with
+ | None ->
+ Pretyping.understand_gen sigma env (rtype l1) (rtype ist.lmatch) ocl c
+ (* If at toplevel (ce<>None), the error can be due to an incorrect
+ context at globalization time: we retype with the now known
+ intros/lettac/inversion hypothesis names *)
+ | Some c -> interp_constr_gen sigma env (l1,l2) ist.lmatch c ocl
+ in
+ db_constr ist.debug env csr;
+ csr
-let interp_openconstr ist gl c ocl =
- interp_openconstr_gen (project gl) (pf_env gl)
- (constr_list ist (pf_env gl)) ist.lmatch c ocl
+let interp_constr ist sigma env c =
+ interp_casted_constr None ist sigma env c
-let pf_interp_constr ist gl =
- interp_constr None ist (project gl) (pf_env gl)
+(* Interprets an open constr expression casted by the current goal *)
+let pf_interp_casted_openconstr ist gl (c,ce) =
+ let sigma = project gl in
+ let env = pf_env gl in
+ let (ltacvar,l) = constr_list ist env in
+ let rtype lst = retype_list sigma env lst in
+ let ocl = Some (pf_concl gl) in
+ match ce with
+ | None ->
+ Pretyping.understand_gen_tcc sigma env (rtype ltacvar) (rtype ist.lmatch)
+ ocl c
+ (* If at toplevel (ce<>None), the error can be due to an incorrect
+ context at globalization time: we retype with the now known
+ intros/lettac/inversion hypothesis names *)
+ | Some c -> interp_openconstr_gen sigma env (ltacvar,l) ist.lmatch c ocl
(* Interprets a constr expression *)
-let constr_interp ist sigma env c =
- let csr = interp_constr None ist sigma env c in
- begin
- db_constr ist.debug env csr;
- csr
- end
-
-let pf_constr_interp ist gl c = constr_interp ist (project gl) (pf_env gl) c
+let pf_interp_constr ist gl =
+ interp_constr ist (project gl) (pf_env gl)
(* Interprets a constr expression casted by the current goal *)
-let cast_constr_interp ist gl c =
- let csr = interp_constr (Some (pf_concl gl)) ist (project gl) (pf_env gl) c in
- db_constr ist.debug (pf_env gl) csr;
- csr
-
-(* Interprets an open constr expression casted by the current goal *)
-let cast_openconstr_interp ist gl c =
- interp_openconstr ist gl c (Some (pf_concl gl))
+let pf_interp_casted_constr ist gl c =
+ interp_casted_constr (Some(pf_concl gl)) ist (project gl) (pf_env gl) c
(* Interprets a reduction expression *)
-let unfold_interp ist env (l,qid) =
+let interp_unfold ist env (l,qid) =
(l,interp_evaluable_or_metanum ist env qid)
-let flag_interp ist env red =
+let interp_flag ist env red =
{ red
with rConst = List.map (interp_evaluable_or_metanum ist env) red.rConst }
-let pattern_interp ist sigma env (l,c) = (l,constr_interp ist sigma env c)
+let interp_pattern ist sigma env (l,c) = (l,interp_constr ist sigma env c)
-let pf_pattern_interp ist gl = pattern_interp ist (project gl) (pf_env gl)
+let pf_interp_pattern ist gl = interp_pattern ist (project gl) (pf_env gl)
let redexp_interp ist sigma env = function
- | Unfold l -> Unfold (List.map (unfold_interp ist env) l)
- | Fold l -> Fold (List.map (constr_interp ist sigma env) l)
- | Cbv f -> Cbv (flag_interp ist env f)
- | Lazy f -> Lazy (flag_interp ist env f)
- | Pattern l -> Pattern (List.map (pattern_interp ist sigma env) l)
- | Simpl o -> Simpl (option_app (pattern_interp ist sigma env) o)
+ | Unfold l -> Unfold (List.map (interp_unfold ist env) l)
+ | Fold l -> Fold (List.map (interp_constr ist sigma env) 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_app (interp_pattern ist sigma env) o)
| (Red _ | Hnf as r) -> r
- | ExtraRedExpr (s,c) -> ExtraRedExpr (s,constr_interp ist sigma env c)
+ | ExtraRedExpr (s,c) -> ExtraRedExpr (s,interp_constr ist sigma env c)
let pf_redexp_interp ist gl = redexp_interp ist (project gl) (pf_env gl)
@@ -1062,13 +1166,13 @@ let interp_may_eval f ist gl = function
subst_meta [-1,ic] ctxt
with
| Not_found ->
- user_err_loc (loc, "constr_interp",
+ user_err_loc (loc, "interp_may_eval",
str "Unbound context identifier" ++ pr_id s))
| ConstrTypeOf c -> pf_type_of gl (f ist gl c)
| ConstrTerm c -> f ist gl c
(* Interprets a constr expression possibly to first evaluate *)
-let constr_interp_may_eval ist gl c =
+let interp_constr_may_eval ist gl c =
let csr = interp_may_eval pf_interp_constr ist gl c in
begin
db_constr ist.debug (pf_env gl) csr;
@@ -1095,45 +1199,42 @@ let interp_quantified_hypothesis ist gl = function
with Not_found -> NamedHyp id
let interp_induction_arg ist gl = function
- | ElimOnConstr c -> ElimOnConstr (pf_constr_interp ist gl c)
+ | ElimOnConstr c -> ElimOnConstr (pf_interp_constr ist gl c)
| ElimOnAnonHyp n as x -> x
| ElimOnIdent (loc,id) ->
if Tactics.is_quantified_hypothesis id gl then ElimOnIdent (loc,id)
- else ElimOnConstr (pf_constr_interp ist gl (CRef (Ident (loc,id))))
+ else ElimOnConstr (pf_interp_constr ist gl (RVar (loc,id),None))
-let binding_interp ist gl (loc,b,c) =
- (loc,interp_quantified_hypothesis ist gl b,pf_constr_interp ist gl c)
+let interp_binding ist gl (loc,b,c) =
+ (loc,interp_quantified_hypothesis ist gl b,pf_interp_constr ist gl c)
-let bindings_interp ist gl = function
+let interp_bindings ist gl = function
| NoBindings -> NoBindings
-| ImplicitBindings l -> ImplicitBindings (List.map (pf_constr_interp ist gl) l)
-| ExplicitBindings l -> ExplicitBindings (List.map (binding_interp ist gl) l)
+| ImplicitBindings l -> ImplicitBindings (List.map (pf_interp_constr ist gl) l)
+| ExplicitBindings l -> ExplicitBindings (List.map (interp_binding ist gl) l)
let interp_constr_with_bindings ist gl (c,bl) =
- (pf_constr_interp ist gl c, bindings_interp ist gl bl)
-
-(* Interprets a l-tac expression into a value *)
-let rec val_interp ist gl tac =
-
- let value_interp ist =
- match tac with
- (* Immediate evaluation *)
- | TacFun (it,body) -> VFun (ist.lfun,it,body)
- | TacLetRecIn (lrc,u) -> letrec_interp ist gl lrc u
- | TacLetIn (l,u) ->
- let addlfun = letin_interp ist gl l in
- val_interp { ist with lfun=addlfun@ist.lfun } gl u
- | TacMatchContext (lr,lmr) -> match_context_interp ist gl lr lmr
- | TacMatch (c,lmr) -> match_interp ist gl c lmr
- | TacArg a -> tacarg_interp ist gl a
- (* Delayed evaluation *)
- | t -> VTactic (dummy_loc,eval_tactic ist t)
- in
- match ist.debug with
- | DebugOn | Run _ ->
- let debug = debug_prompt gl ist.debug tac in
- value_interp {ist with debug=debug}
- | _ -> value_interp ist
+ (pf_interp_constr ist gl c, interp_bindings ist gl bl)
+
+(* Interprets an l-tac expression into a value *)
+let rec val_interp ist gl (tac:glob_tactic_expr) =
+
+ let ist = match ist.debug with
+ | DebugOn | Run _ -> {ist with debug = debug_prompt gl ist.debug tac }
+ | _ -> ist in
+
+ match tac with
+ (* Immediate evaluation *)
+ | TacFun (it,body) -> VFun (ist.lfun,it,body)
+ | TacLetRecIn (lrc,u) -> letrec_interp ist gl lrc u
+ | TacLetIn (l,u) ->
+ let addlfun = interp_letin ist gl l in
+ val_interp { ist with lfun=addlfun@ist.lfun } gl u
+ | TacMatchContext (lr,lmr) -> match_context_interp ist gl lr lmr
+ | TacMatch (c,lmr) -> match_interp ist gl c lmr
+ | TacArg a -> interp_tacarg ist gl a
+ (* Delayed evaluation *)
+ | t -> VTactic (dummy_loc,eval_tactic ist t)
and eval_tactic ist = function
| TacAtom (loc,t) -> fun gl -> catch_error loc (interp_atomic ist gl t) gl
@@ -1145,41 +1246,33 @@ and eval_tactic ist = function
| TacMatch (c,lmr) -> assert false
| TacId -> tclIDTAC
| TacFail (n,s) -> tclFAIL n s
- | TacProgress tac -> tclPROGRESS (tactic_interp ist tac)
- | TacAbstract (tac,s) -> Tactics.tclABSTRACT s (tactic_interp ist tac)
- | TacThen (t1,t2) -> tclTHEN (tactic_interp ist t1) (tactic_interp ist t2)
+ | TacProgress tac -> tclPROGRESS (interp_tactic ist tac)
+ | TacAbstract (tac,s) -> Tactics.tclABSTRACT s (interp_tactic ist tac)
+ | TacThen (t1,t2) -> tclTHEN (interp_tactic ist t1) (interp_tactic ist t2)
| TacThens (t,tl) ->
- tclTHENS (tactic_interp ist t) (List.map (tactic_interp ist) tl)
- | TacDo (n,tac) -> tclDO n (tactic_interp ist tac)
- | TacTry tac -> tclTRY (tactic_interp ist tac)
- | TacInfo tac -> tclINFO (tactic_interp ist tac)
- | TacRepeat tac -> tclREPEAT (tactic_interp ist tac)
+ tclTHENS (interp_tactic ist t) (List.map (interp_tactic ist) tl)
+ | TacDo (n,tac) -> tclDO n (interp_tactic ist tac)
+ | TacTry tac -> tclTRY (interp_tactic ist tac)
+ | TacInfo tac -> tclINFO (interp_tactic ist tac)
+ | TacRepeat tac -> tclREPEAT (interp_tactic ist tac)
| TacOrelse (tac1,tac2) ->
- tclORELSE (tactic_interp ist tac1) (tactic_interp ist tac2)
- | TacFirst l -> tclFIRST (List.map (tactic_interp ist) l)
- | TacSolve l -> tclSOLVE (List.map (tactic_interp ist) l)
+ tclORELSE (interp_tactic ist tac1) (interp_tactic ist tac2)
+ | TacFirst l -> tclFIRST (List.map (interp_tactic ist) l)
+ | TacSolve l -> tclSOLVE (List.map (interp_tactic ist) l)
| TacArg a -> assert false
-and interp_ltac_qualid is_applied ist gl (loc,qid as lqid) =
- try
- let v = val_interp {lfun=[];lmatch=[];debug=ist.debug} gl (lookup qid) in
- if is_applied then v else locate_tactic_call loc v
- with
- Not_found -> interp_pure_qualid is_applied (pf_env gl) lqid
-
and interp_ltac_reference isapplied ist gl = function
- | Ident (loc,id) ->
- (try unrec (List.assoc id ist.lfun)
- with | Not_found ->
- interp_ltac_qualid isapplied ist gl (loc,make_short_qualid id))
- | Qualid qid -> interp_ltac_qualid isapplied ist gl qid
+ | ArgVar (loc,id) -> unrec (List.assoc id ist.lfun)
+ | ArgArg qid ->
+ let v = val_interp {lfun=[];lmatch=[];debug=ist.debug} gl (lookup qid) in
+ if isapplied then v else locate_tactic_call loc v
-and tacarg_interp ist gl = function
+and interp_tacarg ist gl = function
| TacVoid -> VVoid
| Reference r -> interp_ltac_reference false ist gl r
| Integer n -> VInteger n
- | ConstrMayEval c -> VConstr (constr_interp_may_eval ist gl c)
- | MetaNumArg (_,n) -> VConstr (List.assoc n ist.lmatch)
+ | Identifier id -> VIdentifier id
+ | ConstrMayEval c -> VConstr (interp_constr_may_eval ist gl c)
| MetaIdArg (loc,id) ->
(try (* $id can occur in Grammar tactic... *)
(unrec (List.assoc (id_of_string id) ist.lfun))
@@ -1187,14 +1280,20 @@ and tacarg_interp ist gl = function
| Not_found -> error_syntactic_metavariables_not_allowed loc)
| TacCall (loc,f,l) ->
let fv = interp_ltac_reference true ist gl f
- and largs = List.map (tacarg_interp ist gl) l in
+ and largs = List.map (interp_tacarg ist gl) l in
List.iter check_is_value largs;
- app_interp ist gl fv largs loc
+ interp_app ist gl fv largs loc
| Tacexp t -> val_interp ist gl t
| TacDynamic(_,t) ->
let tg = (tag t) in
if tg = "tactic" then
- let f = (tactic_out t) in val_interp ist gl (f ist)
+ let f = (tactic_out t) in
+ val_interp ist gl
+ (intern_tactic {
+ ltacvars = (List.map fst ist.lfun,[]); ltacrecvars = [];
+ metavars = List.map fst ist.lmatch;
+ gsigma = project gl; genv = pf_env gl }
+ (f ist))
else if tg = "value" then
value_out t
else if tg = "constr" then
@@ -1204,18 +1303,18 @@ and tacarg_interp ist gl = function
(str "Unknown dynamic: <" ++ str (Dyn.tag t) ++ str ">"))
(* Interprets an application node *)
-and app_interp ist gl fv largs loc =
+and interp_app ist gl fv largs loc =
match fv with
| VFun(olfun,var,body) ->
let (newlfun,lvar,lval)=head_with_value (var,largs) in
if lvar=[] then
let v = val_interp { ist with lfun=newlfun@olfun } gl body in
if lval=[] then locate_tactic_call loc v
- else app_interp ist gl v lval loc
+ else interp_app ist gl v lval loc
else
VFun(newlfun@olfun,lvar,body)
| _ ->
- user_err_loc (loc, "Tacinterp.app_interp",
+ user_err_loc (loc, "Tacinterp.interp_app",
(str"Illegal tactic application"))
(* Gives the tactic corresponding to the tactic value *)
@@ -1227,9 +1326,9 @@ and tactic_of_value vle g =
| _ -> raise NotTactic
(* Evaluation with FailError catching *)
-and eval_with_fail interp tac goal =
+and eval_with_fail ist tac goal =
try
- (match interp goal tac with
+ (match val_interp ist goal tac with
| VTactic (loc,tac) -> VRTactic (catch_error loc tac goal)
| a -> a)
with
@@ -1254,15 +1353,15 @@ and letrec_interp ist gl lrc u =
end
(* Interprets the clauses of a LetIn *)
-and letin_interp ist gl = function
+and interp_letin ist gl = function
| [] -> []
| ((loc,id),None,t)::tl ->
- let v = tacarg_interp ist gl t in
+ let v = interp_tacarg ist gl t in
check_is_value v;
- (id,v):: (letin_interp ist gl tl)
+ (id,v):: (interp_letin ist gl tl)
| ((loc,id),Some com,tce)::tl ->
let typ = interp_may_eval pf_interp_constr ist gl com
- and v = tacarg_interp ist gl tce in
+ and v = interp_tacarg ist gl tce in
let csr =
try
constr_of_value (pf_env gl) v
@@ -1277,16 +1376,16 @@ and letin_interp ist gl = function
pft
with | NotTactic ->
delete_proof (dummy_loc,id);
- errorlabstrm "Tacinterp.letin_interp"
+ errorlabstrm "Tacinterp.interp_letin"
(str "Term or fully applied tactic expected in Let")
- in (id,VConstr (mkCast (csr,typ)))::(letin_interp ist gl tl)
+ in (id,VConstr (mkCast (csr,typ)))::(interp_letin ist gl tl)
(* Interprets the clauses of a LetCut *)
and letcut_interp ist = function
| [] -> tclIDTAC
| (id,c,tce)::tl -> fun gl ->
- let typ = constr_interp_may_eval ist gl c
- and v = tacarg_interp ist gl tce in
+ let typ = interp_constr_may_eval ist gl c
+ and v = interp_tacarg ist gl tce in
let csr =
try
constr_of_value (pf_env gl) v
@@ -1300,7 +1399,7 @@ and letcut_interp ist = function
pft
with | NotTactic ->
delete_proof (dummy_loc,id);
- errorlabstrm "Tacinterp.letin_interp"
+ errorlabstrm "Tacinterp.interp_letin"
(str "Term or fully applied tactic expected in Let")
in
let cutt = h_cut typ
@@ -1314,8 +1413,7 @@ and match_context_interp ist g lr lmr =
let (lgoal,ctxt) = sub_match nocc c csr in
let lctxt = give_context ctxt id in
if mhyps = [] then
- eval_with_fail
- (val_interp {ist with lfun=lctxt@ist.lfun; lmatch=lgoal@ist.lmatch})
+ eval_with_fail {ist with lfun=lctxt@ist.lfun; lmatch=lgoal@ist.lmatch}
mt goal
else
apply_hyps_context ist env goal mt lgoal mhyps hyps
@@ -1331,7 +1429,7 @@ and match_context_interp ist g lr lmr =
| (All t)::tl ->
begin
db_mc_pattern_success ist.debug;
- try eval_with_fail (val_interp ist) t goal
+ try eval_with_fail ist t goal
with e when is_match_catchable e ->
apply_match_context ist env goal (nrs+1) (List.tl lex) tl
end
@@ -1349,8 +1447,7 @@ and match_context_interp ist g lr lmr =
if mhyps = [] then
begin
db_mc_pattern_success ist.debug;
- eval_with_fail (val_interp
- {ist with lmatch=lgoal@ist.lmatch}) mt goal
+ eval_with_fail {ist with lmatch=lgoal@ist.lmatch} mt goal
end
else
apply_hyps_context ist env goal mt lgoal mhyps hyps
@@ -1369,7 +1466,8 @@ and match_context_interp ist g lr lmr =
with e when is_match_catchable e ->
apply_match_context ist env goal (nrs+1) (List.tl lex) tl))
| _ ->
- errorlabstrm "Tacinterp.apply_match_context"
+ errorlabstrm "Tacinterp.apply_match_context" (str
+ "No matching clauses for Match Context")
(v 0 (str "No matching clauses for Match Context" ++
(if ist.debug=DebugOff then
fnl() ++ str "(use \"Debug On\" for more info)"
@@ -1377,7 +1475,7 @@ and match_context_interp ist g lr lmr =
end in
let env = pf_env g in
apply_match_context ist env g 0 lmr
- (read_match_rule (project g) env (constr_list ist env) lmr)
+ (read_match_rule (project g) env (fst (constr_list ist env)) lmr)
(* Tries to match the hypotheses in a Match Context *)
and apply_hyps_context ist env goal mt lgmatch mhyps hyps =
@@ -1394,8 +1492,8 @@ and apply_hyps_context ist env goal mt lgmatch mhyps hyps =
if tl = [] then
begin
db_mc_pattern_success ist.debug;
- eval_with_fail (val_interp {ist with lfun=lfun@lid@lc@ist.lfun;
- lmatch=lmatch@lm@ist.lmatch}) mt goal
+ eval_with_fail {ist with lfun=lfun@lid@lc@ist.lfun;
+ lmatch=lmatch@lm@ist.lmatch} mt goal
end
else
let nextlhyps =
@@ -1420,48 +1518,49 @@ and apply_hyps_context ist env goal mt lgmatch mhyps hyps =
apply_hyps_context_rec ist mt [] lgmatch mhyps hyps hyps None
(* Interprets extended tactic generic arguments *)
-and genarg_interp ist goal x =
+and interp_genarg ist goal x =
match genarg_tag x with
- | BoolArgType -> in_gen wit_bool (out_gen rawwit_bool x)
- | IntArgType -> in_gen wit_int (out_gen rawwit_int x)
+ | BoolArgType -> in_gen wit_bool (out_gen globwit_bool x)
+ | IntArgType -> in_gen wit_int (out_gen globwit_int x)
| IntOrVarArgType ->
let f = function
| ArgVar locid -> eval_integer ist.lfun locid
| ArgArg n as x -> x in
- in_gen wit_int_or_var (f (out_gen rawwit_int_or_var x))
+ in_gen wit_int_or_var (f (out_gen globwit_int_or_var x))
| StringArgType ->
- in_gen wit_string (out_gen rawwit_string x)
+ in_gen wit_string (out_gen globwit_string x)
| PreIdentArgType ->
- in_gen wit_pre_ident (out_gen rawwit_pre_ident x)
+ in_gen wit_pre_ident (out_gen globwit_pre_ident x)
| IdentArgType ->
- in_gen wit_ident (eval_ident ist (out_gen rawwit_ident x))
+ in_gen wit_ident (eval_ident ist (out_gen globwit_ident x))
| RefArgType ->
- in_gen wit_ref (pf_reference_interp ist goal (out_gen rawwit_ref x))
+ in_gen wit_ref (pf_interp_reference ist goal (out_gen globwit_ref x))
| SortArgType ->
in_gen wit_sort
(destSort
- (pf_constr_interp ist goal (CSort (dummy_loc,out_gen rawwit_sort x))))
+ (pf_interp_constr ist goal
+ (RSort (dummy_loc,out_gen globwit_sort x), None)))
| ConstrArgType ->
- in_gen wit_constr (pf_constr_interp ist goal (out_gen rawwit_constr x))
+ in_gen wit_constr (pf_interp_constr ist goal (out_gen globwit_constr x))
| ConstrMayEvalArgType ->
- in_gen wit_constr_may_eval (constr_interp_may_eval ist goal (out_gen rawwit_constr_may_eval x))
+ in_gen wit_constr_may_eval (interp_constr_may_eval ist goal (out_gen globwit_constr_may_eval x))
| QuantHypArgType ->
in_gen wit_quant_hyp
- (interp_quantified_hypothesis ist goal (out_gen rawwit_quant_hyp x))
+ (interp_quantified_hypothesis ist goal (out_gen globwit_quant_hyp x))
| RedExprArgType ->
- in_gen wit_red_expr (pf_redexp_interp ist goal (out_gen rawwit_red_expr x))
- | TacticArgType -> in_gen wit_tactic (out_gen rawwit_tactic x)
+ in_gen wit_red_expr (pf_redexp_interp ist goal (out_gen globwit_red_expr x))
+ | TacticArgType -> in_gen wit_tactic (out_gen globwit_tactic x)
| CastedOpenConstrArgType ->
in_gen wit_casted_open_constr
- (cast_openconstr_interp ist goal (out_gen rawwit_casted_open_constr x))
+ (pf_interp_casted_openconstr ist goal (out_gen globwit_casted_open_constr x))
| ConstrWithBindingsArgType ->
in_gen wit_constr_with_bindings
- (interp_constr_with_bindings ist goal (out_gen rawwit_constr_with_bindings x))
- | List0ArgType _ -> app_list0 (genarg_interp ist goal) x
- | List1ArgType _ -> app_list1 (genarg_interp ist goal) x
- | OptArgType _ -> app_opt (genarg_interp ist goal) x
- | PairArgType _ -> app_pair (genarg_interp ist goal) (genarg_interp ist goal) x
- | ExtraArgType s -> lookup_genarg_interp s ist goal x
+ (interp_constr_with_bindings ist goal (out_gen globwit_constr_with_bindings x))
+ | List0ArgType _ -> app_list0 (interp_genarg ist goal) x
+ | List1ArgType _ -> app_list1 (interp_genarg ist goal) x
+ | OptArgType _ -> app_opt (interp_genarg ist goal) x
+ | PairArgType _ -> app_pair (interp_genarg ist goal) (interp_genarg ist goal) x
+ | ExtraArgType s -> lookup_interp_genarg s ist goal x
(* Interprets the Match expressions *)
and match_interp ist g constr lmr =
@@ -1489,16 +1588,16 @@ and match_interp ist g constr lmr =
| _ ->
errorlabstrm "Tacinterp.apply_match" (str
"No matching clauses for Match") in
- let csr = constr_interp_may_eval ist g constr in
+ let csr = interp_constr_may_eval ist g constr in
let env = pf_env g in
- let ilr = read_match_rule (project g) env (constr_list ist env) lmr in
+ let ilr = read_match_rule (project g) env (fst (constr_list ist env)) lmr in
apply_match ist csr ilr
(* Interprets tactic expressions : returns a "tactic" *)
-and tactic_interp ist tac gl =
+and interp_tactic ist tac gl =
try tactic_of_value (val_interp ist gl tac) gl
with | NotTactic ->
- errorlabstrm "Tacinterp.tac_interp" (str
+ errorlabstrm "Tacinterp.interp_tactic" (str
"Must be a command or must give a tactic value")
(* Interprets a primitive tactic *)
@@ -1512,43 +1611,46 @@ and interp_atomic ist gl = function
h_intro_move (option_app (eval_ident ist) ido)
(option_app (fun x -> eval_variable ist gl x) ido')
| TacAssumption -> h_assumption
- | TacExact c -> h_exact (cast_constr_interp ist gl c)
+ | TacExact c -> h_exact (pf_interp_casted_constr ist gl c)
| TacApply cb -> h_apply (interp_constr_with_bindings ist gl cb)
| TacElim (cb,cbo) ->
h_elim (interp_constr_with_bindings ist gl cb)
(option_app (interp_constr_with_bindings ist gl) cbo)
- | TacElimType c -> h_elim_type (pf_constr_interp ist gl c)
+ | TacElimType c -> h_elim_type (pf_interp_constr ist gl c)
| TacCase cb -> h_case (interp_constr_with_bindings ist gl cb)
- | TacCaseType c -> h_case_type (pf_constr_interp ist gl c)
+ | TacCaseType c -> h_case_type (pf_interp_constr ist gl c)
| TacFix (idopt,n) -> h_fix (eval_opt_ident ist idopt) n
| TacMutualFix (id,n,l) ->
- let f (id,n,c) = (eval_ident ist id,n,pf_constr_interp ist gl c) in
+ let f (id,n,c) = (eval_ident ist id,n,pf_interp_constr ist gl c) in
h_mutual_fix (eval_ident ist id) n (List.map f l)
| TacCofix idopt -> h_cofix (eval_opt_ident ist idopt)
| TacMutualCofix (id,l) ->
- let f (id,c) = (eval_ident ist id,pf_constr_interp ist gl c) in
+ let f (id,c) = (eval_ident ist id,pf_interp_constr ist gl c) in
h_mutual_cofix (eval_ident ist id) (List.map f l)
- | TacCut c -> h_cut (pf_constr_interp ist gl c)
- | TacTrueCut (ido,c) -> h_true_cut (eval_opt_ident ist ido) (pf_constr_interp ist gl c)
- | TacForward (b,na,c) -> h_forward b (eval_name ist na) (pf_constr_interp ist gl c)
- | TacGeneralize cl -> h_generalize (List.map (pf_constr_interp ist gl) cl)
- | TacGeneralizeDep c -> h_generalize_dep (pf_constr_interp ist gl c)
+ | TacCut c -> h_cut (pf_interp_constr ist gl c)
+ | TacTrueCut (ido,c) ->
+ h_true_cut (eval_opt_ident ist ido) (pf_interp_constr ist gl c)
+ | TacForward (b,na,c) ->
+ h_forward b (eval_name ist na) (pf_interp_constr ist gl c)
+ | TacGeneralize cl -> h_generalize (List.map (pf_interp_constr ist gl) cl)
+ | TacGeneralizeDep c -> h_generalize_dep (pf_interp_constr ist gl c)
| TacLetTac (id,c,clp) ->
let clp = check_clause_pattern ist gl clp in
- h_let_tac (eval_ident ist id) (pf_constr_interp ist gl c) clp
- | TacInstantiate (n,c) -> h_instantiate n (pf_constr_interp ist gl c)
+ h_let_tac (eval_ident ist id) (pf_interp_constr ist gl c) clp
+ | TacInstantiate (n,c) -> h_instantiate n (pf_interp_constr ist gl c)
(* Automation tactics *)
| TacTrivial l -> Auto.h_trivial l
| TacAuto (n, l) -> Auto.h_auto n l
| TacAutoTDB n -> Dhyp.h_auto_tdb n
- | TacDestructHyp (b,id) -> Dhyp.h_destructHyp b (hyp_interp ist gl id)
+ | TacDestructHyp (b,id) -> Dhyp.h_destructHyp b (interp_hyp ist gl id)
| TacDestructConcl -> Dhyp.h_destructConcl
| TacSuperAuto (n,l,b1,b2) -> Auto.h_superauto n l b1 b2
| TacDAuto (n,p) -> Auto.h_dauto (n,p)
(* Derived basic tactics *)
- | TacOldInduction h -> h_old_induction (interp_quantified_hypothesis ist gl h)
+ | TacOldInduction h ->
+ h_old_induction (interp_quantified_hypothesis ist gl h)
| TacNewInduction (c,cbo,ids) ->
h_new_induction (interp_induction_arg ist gl c)
(option_app (interp_constr_with_bindings ist gl) cbo)
@@ -1562,79 +1664,367 @@ and interp_atomic ist gl = function
let h1 = interp_quantified_hypothesis ist gl h1 in
let h2 = interp_quantified_hypothesis ist gl h2 in
Elim.h_double_induction h1 h2
- | TacDecomposeAnd c -> Elim.h_decompose_and (pf_constr_interp ist gl c)
- | TacDecomposeOr c -> Elim.h_decompose_or (pf_constr_interp ist gl c)
+ | TacDecomposeAnd c -> Elim.h_decompose_and (pf_interp_constr ist gl c)
+ | TacDecomposeOr c -> Elim.h_decompose_or (pf_interp_constr ist gl c)
| TacDecompose (l,c) ->
- let l = List.map (interp_inductive_or_metanum ist gl) l in
- Elim.h_decompose l (pf_constr_interp ist gl c)
- | TacSpecialize (n,l) -> h_specialize n (interp_constr_with_bindings ist gl l)
- | TacLApply c -> h_lapply (pf_constr_interp ist gl c)
+ let l = List.map (interp_inductive_or_metanum 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)
+ | TacLApply c -> h_lapply (pf_interp_constr ist gl c)
(* Context management *)
- | TacClear l -> h_clear (List.map (hyp_or_metanum_interp ist gl) l)
- | TacClearBody l -> h_clear_body (List.map (hyp_or_metanum_interp ist gl) l)
+ | TacClear l -> h_clear (List.map (interp_hyp_or_metanum ist gl) l)
+ | TacClearBody l -> h_clear_body (List.map (interp_hyp_or_metanum ist gl) l)
| TacMove (dep,id1,id2) ->
- h_move dep (hyp_interp ist gl id1) (hyp_interp ist gl id2)
+ h_move dep (interp_hyp ist gl id1) (interp_hyp ist gl id2)
| TacRename (id1,id2) ->
- h_rename (hyp_interp ist gl id1) (eval_ident ist (snd id2))
+ h_rename (interp_hyp ist gl id1) (eval_ident ist (snd id2))
(* Constructors *)
- | TacLeft bl -> h_left (bindings_interp ist gl bl)
- | TacRight bl -> h_right (bindings_interp ist gl bl)
- | TacSplit (_,bl) -> h_split (bindings_interp ist gl bl)
+ | TacLeft bl -> h_left (interp_bindings ist gl bl)
+ | TacRight bl -> h_right (interp_bindings ist gl bl)
+ | TacSplit (_,bl) -> h_split (interp_bindings ist gl bl)
| TacAnyConstructor t ->
abstract_tactic (TacAnyConstructor t)
- (Tactics.any_constructor (option_app (tactic_interp ist) t))
+ (Tactics.any_constructor (option_app (interp_tactic ist) t))
| TacConstructor (n,bl) ->
- h_constructor (skip_metaid n) (bindings_interp ist gl bl)
+ h_constructor (skip_metaid n) (interp_bindings ist gl bl)
(* Conversion *)
| TacReduce (r,cl) ->
h_reduce (pf_redexp_interp ist gl r) (List.map
(interp_hyp_location ist gl) cl)
| TacChange (occl,c,cl) ->
- h_change (option_app (pf_pattern_interp ist gl) occl)
- (pf_constr_interp ist gl c) (List.map (interp_hyp_location ist gl) cl)
+ h_change (option_app (pf_interp_pattern ist gl) occl)
+ (pf_interp_constr ist gl c) (List.map (interp_hyp_location ist gl) cl)
(* Equivalence relations *)
| TacReflexivity -> h_reflexivity
| TacSymmetry -> h_symmetry
- | TacTransitivity c -> h_transitivity (pf_constr_interp ist gl c)
+ | TacTransitivity c -> h_transitivity (pf_interp_constr ist gl c)
(* For extensions *)
| TacExtend (loc,opn,l) ->
- fun gl -> vernac_tactic (opn,List.map (genarg_interp ist gl) l) gl
+ fun gl -> vernac_tactic (opn,List.map (interp_genarg ist gl) l) gl
| TacAlias (_,l,body) -> fun gl ->
let f x = match genarg_tag x with
| IdentArgType ->
- let id = out_gen rawwit_ident x in
+ let id = out_gen globwit_ident x in
(try VConstr (mkVar (eval_variable ist gl (dummy_loc,id)))
with Not_found -> VIdentifier id)
- | RefArgType -> VConstr (constr_of_reference (pf_reference_interp ist gl (out_gen rawwit_ref x)))
- | ConstrArgType -> VConstr (pf_constr_interp ist gl (out_gen rawwit_constr x))
+ | RefArgType ->
+ VConstr (constr_of_reference
+ (pf_interp_reference ist gl (out_gen globwit_ref x)))
+ | ConstrArgType ->
+ VConstr (pf_interp_constr ist gl (out_gen globwit_constr x))
| ConstrMayEvalArgType ->
- VConstr (constr_interp_may_eval ist gl (out_gen rawwit_constr_may_eval x))
+ VConstr
+ (interp_constr_may_eval ist gl (out_gen globwit_constr_may_eval x))
| _ -> failwith "This generic type is not supported in alias"
in
let lfun = (List.map (fun (x,c) -> (x,f c)) l)@ist.lfun in
tactic_of_value (val_interp { ist with lfun=lfun } gl body) gl
-(* Interprets tactic arguments *)
-let interp_tacarg sign ast = val_interp sign ast
-
(* Initial call for interpretation *)
-let tac_interp lfun lmatch debug t =
- tactic_interp { lfun=lfun; lmatch=lmatch; debug=debug } t
+let interp_tac_gen lfun lmatch debug t gl =
+ interp_tactic { lfun=lfun; lmatch=lmatch; debug=debug }
+ (intern_tactic {
+ ltacvars = (List.map fst lfun, []); ltacrecvars = [];
+ metavars = List.map fst lmatch;
+ gsigma = project gl; genv = pf_env gl } t) gl
-let interp = fun t -> tac_interp [] [] (get_debug()) t (* Side-effect *)
+let eval_tactic t = interp_tactic { lfun=[]; lmatch=[]; debug=get_debug() } t
+
+let interp t = interp_tac_gen [] [] (get_debug()) t
(* Hides interpretation for pretty-print *)
let hide_interp t ot gl =
- let te = glob_tactic ([],[],project gl,pf_env gl) t in
+ let ist = { ltacvars = ([],[]); ltacrecvars = []; metavars = [];
+ gsigma = project gl; genv = pf_env gl } in
+ let te = intern_tactic ist t in
+ let t = eval_tactic te in
match ot with
- | None -> abstract_tactic_expr (TacArg (Tacexp t)) (interp t) gl
- | Some t' ->
- abstract_tactic_expr (TacArg (Tacexp t)) (tclTHEN (interp t) t') gl
+ | None -> abstract_tactic_expr (TacArg (Tacexp te)) t gl
+ | Some t' -> abstract_tactic_expr (TacArg (Tacexp te)) (tclTHEN t t') gl
+
+(***************************************************************************)
+(* Substitution at module closing time *)
+
+let subst_quantified_hypothesis _ x = x
+
+let subst_inductive subst (kn,i) = (subst_kn subst kn,i)
+
+let subst_rawconstr subst (c,e) =
+ assert (e=None); (* e<>None only for toplevel tactics *)
+ (subst_raw subst c,None)
+
+let subst_binding subst (loc,b,c) =
+ (loc,subst_quantified_hypothesis subst b,subst_rawconstr subst c)
+
+let subst_bindings subst = function
+ | NoBindings -> NoBindings
+ | ImplicitBindings l -> ImplicitBindings (List.map (subst_rawconstr subst) l)
+ | ExplicitBindings l -> ExplicitBindings (List.map (subst_binding subst) l)
+
+let subst_raw_with_bindings subst (c,bl) =
+ (subst_rawconstr subst c, subst_bindings subst bl)
+
+let subst_induction_arg subst = function
+ | ElimOnConstr c -> ElimOnConstr (subst_rawconstr subst c)
+ | ElimOnAnonHyp n as x -> x
+ | ElimOnIdent id as x -> x
+
+let subst_evaluable_reference subst = function
+ | EvalVarRef id -> EvalVarRef id
+ | EvalConstRef kn -> EvalConstRef (subst_kn subst kn)
+
+let subst_and_short_name f (c,n) =
+ assert (n=None); (* since tacdef are strictly globalized *)
+ (f c,None)
+
+let subst_or_metanum f = function
+ | AN x -> AN (f x)
+ | MetaNum (_loc,n) -> MetaNum (loc,n)
+
+let subst_or_var f = function
+ | ArgVar _ as x -> x
+ | ArgArg (x) -> ArgArg (f x)
+
+let subst_located f (_loc,id) = (loc,f id)
+
+let subst_reference subst r = (* TODO: subst ltac global names *) r
+
+let subst_global_reference subst =
+ subst_or_var (subst_located (subst_global subst))
+
+let subst_evaluable subst =
+ subst_or_metanum (subst_or_var
+ (subst_and_short_name (subst_evaluable_reference subst)))
+
+let subst_unfold subst (l,e) =
+ (l,subst_evaluable subst e)
+
+let subst_flag subst red =
+ { red with rConst = List.map (subst_evaluable subst) red.rConst }
+
+let subst_constr_occurrence subst (l,c) = (l,subst_rawconstr subst c)
+
+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_occurrence subst) l)
+ | Simpl o -> Simpl (option_app (subst_constr_occurrence subst) o)
+ | (Red _ | Hnf as r) -> r
+ | ExtraRedExpr (s,c) -> ExtraRedExpr (s, subst_rawconstr subst c)
+
+let subst_raw_may_eval subst = function
+ | ConstrEval (r,c) -> ConstrEval (subst_redexp subst r,subst_rawconstr subst c)
+ | ConstrContext (locid,c) -> ConstrContext (locid,subst_rawconstr subst c)
+ | ConstrTypeOf c -> ConstrTypeOf (subst_rawconstr subst c)
+ | ConstrTerm c -> ConstrTerm (subst_rawconstr subst c)
+
+let subst_match_pattern subst = function
+ | Subterm (ido,pc) -> Subterm (ido,subst_pattern subst pc)
+ | Term pc -> Term (subst_pattern subst pc)
+
+let rec subst_match_context_hyps subst = function
+ | NoHypId mp :: tl ->
+ NoHypId (subst_match_pattern subst mp)
+ :: subst_match_context_hyps subst tl
+ | Hyp (locs,mp) :: tl ->
+ Hyp (locs,subst_match_pattern subst mp)
+ :: subst_match_context_hyps subst tl
+ | [] -> []
+
+let rec subst_atomic subst (t:glob_atomic_tactic_expr) = match t with
+ (* Basic tactics *)
+ | TacIntroPattern _ | TacIntrosUntil _ | TacIntroMove _ as x -> x
+ | TacAssumption as x -> x
+ | TacExact c -> TacExact (subst_rawconstr subst c)
+ | TacApply cb -> TacApply (subst_raw_with_bindings subst cb)
+ | TacElim (cb,cbo) ->
+ TacElim (subst_raw_with_bindings subst cb,
+ option_app (subst_raw_with_bindings subst) cbo)
+ | TacElimType c -> TacElimType (subst_rawconstr subst c)
+ | TacCase cb -> TacCase (subst_raw_with_bindings subst cb)
+ | TacCaseType c -> TacCaseType (subst_rawconstr subst c)
+ | TacFix (idopt,n) as x -> x
+ | TacMutualFix (id,n,l) ->
+ TacMutualFix(id,n,List.map (fun (id,n,c) -> (id,n,subst_rawconstr subst c)) l)
+ | TacCofix idopt as x -> x
+ | TacMutualCofix (id,l) ->
+ TacMutualCofix (id, List.map (fun (id,c) -> (id,subst_rawconstr subst c)) l)
+ | TacCut c -> TacCut (subst_rawconstr subst c)
+ | TacTrueCut (ido,c) -> TacTrueCut (ido, subst_rawconstr subst c)
+ | TacForward (b,na,c) -> TacForward (b,na,subst_rawconstr subst c)
+ | TacGeneralize cl -> TacGeneralize (List.map (subst_rawconstr subst) cl)
+ | TacGeneralizeDep c -> TacGeneralizeDep (subst_rawconstr subst c)
+ | TacLetTac (id,c,clp) -> TacLetTac (id,subst_rawconstr subst c,clp)
+ | TacInstantiate (n,c) -> TacInstantiate (n,subst_rawconstr subst c)
+
+ (* Automation tactics *)
+ | TacTrivial l -> TacTrivial l
+ | TacAuto (n,l) -> TacAuto (n,l)
+ | TacAutoTDB n -> TacAutoTDB n
+ | TacDestructHyp (b,id) -> TacDestructHyp(b,id)
+ | TacDestructConcl -> TacDestructConcl
+ | TacSuperAuto (n,l,b1,b2) -> TacSuperAuto (n,l,b1,b2)
+ | TacDAuto (n,p) -> TacDAuto (n,p)
+
+ (* Derived basic tactics *)
+ | TacOldInduction h as x -> x
+ | TacNewInduction (c,cbo,ids) ->
+ TacNewInduction (subst_induction_arg subst c,
+ option_app (subst_raw_with_bindings subst) cbo, ids)
+ | TacOldDestruct h as x -> x
+ | TacNewDestruct (c,cbo,ids) ->
+ TacNewDestruct (subst_induction_arg subst c,
+ option_app (subst_raw_with_bindings subst) cbo, ids)
+ | TacDoubleInduction (h1,h2) as x -> x
+ | TacDecomposeAnd c -> TacDecomposeAnd (subst_rawconstr subst c)
+ | TacDecomposeOr c -> TacDecomposeOr (subst_rawconstr subst c)
+ | TacDecompose (l,c) ->
+ let l =
+ List.map (subst_or_metanum (subst_or_var (subst_inductive subst))) l in
+ TacDecompose (l,subst_rawconstr subst c)
+ | TacSpecialize (n,l) -> TacSpecialize (n,subst_raw_with_bindings subst l)
+ | TacLApply c -> TacLApply (subst_rawconstr subst c)
+
+ (* Context management *)
+ | TacClear l as x -> x
+ | TacClearBody l as x -> x
+ | TacMove (dep,id1,id2) as x -> x
+ | TacRename (id1,id2) as x -> x
+
+ (* Constructors *)
+ | TacLeft bl -> TacLeft (subst_bindings subst bl)
+ | TacRight bl -> TacRight (subst_bindings subst bl)
+ | TacSplit (b,bl) -> TacSplit (b,subst_bindings subst bl)
+ | TacAnyConstructor t -> TacAnyConstructor (option_app (subst_tactic subst) t)
+ | TacConstructor (n,bl) -> TacConstructor (n, subst_bindings subst bl)
+
+ (* Conversion *)
+ | TacReduce (r,cl) -> TacReduce (subst_redexp subst r, cl)
+ | TacChange (occl,c,cl) ->
+ TacChange (option_app (subst_constr_occurrence subst) occl,
+ subst_rawconstr subst c, cl)
+
+ (* Equivalence relations *)
+ | TacReflexivity | TacSymmetry as x -> x
+ | TacTransitivity c -> TacTransitivity (subst_rawconstr subst c)
+
+ (* For extensions *)
+ | TacExtend (_loc,opn,l) ->
+ let _ = lookup_tactic opn in
+ TacExtend (loc,opn,List.map (subst_genarg subst) l)
+ | TacAlias (s,l,body) ->
+ TacAlias (s,List.map (fun (id,a) -> (id,subst_genarg subst a)) l,subst_tactic subst body)
+
+and subst_tactic subst (t:glob_tactic_expr) = match t with
+ | TacAtom (_loc,t) -> TacAtom (loc, subst_atomic subst t)
+ | TacFun tacfun -> TacFun (subst_tactic_fun subst tacfun)
+ | TacLetRecIn (lrc,u) ->
+ let lrc = List.map (fun (n,b) -> (n,subst_tactic_fun subst b)) lrc in
+ TacLetRecIn (lrc,(subst_tactic subst u:glob_tactic_expr))
+ | TacLetIn (l,u) ->
+ let l = List.map (fun (n,c,b) -> (n,option_app (subst_raw_may_eval subst) c,subst_tacarg subst b)) l in
+ TacLetIn (l,subst_tactic subst u)
+ | TacLetCut l ->
+ let f (n,c,t) = (n,subst_raw_may_eval subst c,subst_tacarg subst t) in
+ TacLetCut (List.map f l)
+ | TacMatchContext (lr,lmr) ->
+ TacMatchContext(lr, subst_match_rule subst lmr)
+ | TacMatch (c,lmr) ->
+ TacMatch (subst_raw_may_eval subst c,subst_match_rule subst lmr)
+ | TacId | TacFail _ as x -> x
+ | TacProgress tac -> TacProgress (subst_tactic subst tac:glob_tactic_expr)
+ | TacAbstract (tac,s) -> TacAbstract (subst_tactic subst tac,s)
+ | TacThen (t1,t2) ->
+ TacThen (subst_tactic subst t1,subst_tactic subst t2)
+ | TacThens (t,tl) ->
+ TacThens (subst_tactic subst t, List.map (subst_tactic subst) tl)
+ | TacDo (n,tac) -> TacDo (n,subst_tactic subst tac)
+ | TacTry tac -> TacTry (subst_tactic subst tac)
+ | TacInfo tac -> TacInfo (subst_tactic subst tac)
+ | TacRepeat tac -> TacRepeat (subst_tactic subst tac)
+ | TacOrelse (tac1,tac2) ->
+ TacOrelse (subst_tactic subst tac1,subst_tactic subst tac2)
+ | TacFirst l -> TacFirst (List.map (subst_tactic subst) l)
+ | TacSolve l -> TacSolve (List.map (subst_tactic subst) l)
+ | TacArg a -> TacArg (subst_tacarg subst a)
+
+and subst_tactic_fun subst (var,body) = (var,subst_tactic subst body)
+
+and subst_tacarg subst = function
+ | TacVoid -> TacVoid
+ | Reference r -> Reference (subst_or_var (subst_reference subst) r)
+ | Identifier id -> Identifier id
+ | Integer n -> Integer n
+ | ConstrMayEval c -> ConstrMayEval (subst_raw_may_eval subst c)
+ | MetaIdArg (_loc,_) -> error_syntactic_metavariables_not_allowed loc
+ | TacCall (_loc,f,l) ->
+ TacCall (_loc,
+ subst_or_var (subst_reference subst) f,
+ List.map (subst_tacarg subst) l)
+ | Tacexp t -> Tacexp (subst_tactic subst t)
+ | TacDynamic(_,t) as x ->
+ (match tag t with
+ | "tactic" | "value" | "constr" -> x
+ | s -> anomaly_loc (loc, "Tacinterp.val_interp",
+ str "Unknown dynamic: <" ++ str s ++ str ">"))
+
+(* Reads the rules of a Match Context or a Match *)
+and subst_match_rule subst = function
+ | (All tc)::tl ->
+ (All (subst_tactic subst tc))::(subst_match_rule subst tl)
+ | (Pat (rl,mp,tc))::tl ->
+ let hyps = subst_match_context_hyps subst rl in
+ let pat = subst_match_pattern subst mp in
+ Pat (hyps,pat,subst_tactic subst tc)
+ ::(subst_match_rule subst tl)
+ | [] -> []
+
+and subst_genarg subst (x:glob_generic_argument) =
+ match genarg_tag x with
+ | BoolArgType -> in_gen globwit_bool (out_gen globwit_bool x)
+ | IntArgType -> in_gen globwit_int (out_gen globwit_int x)
+ | IntOrVarArgType -> in_gen globwit_int_or_var (out_gen globwit_int_or_var x)
+ | StringArgType -> in_gen globwit_string (out_gen globwit_string x)
+ | PreIdentArgType -> in_gen globwit_pre_ident (out_gen globwit_pre_ident x)
+ | IdentArgType -> in_gen globwit_ident (out_gen globwit_ident x)
+ | RefArgType ->
+ in_gen globwit_ref (subst_global_reference subst
+ (out_gen globwit_ref x))
+ | SortArgType ->
+ in_gen globwit_sort (out_gen globwit_sort x)
+ | ConstrArgType ->
+ in_gen globwit_constr (subst_rawconstr subst (out_gen globwit_constr x))
+ | ConstrMayEvalArgType ->
+ 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_quantified_hypothesis subst (out_gen globwit_quant_hyp x))
+ | RedExprArgType ->
+ in_gen globwit_red_expr (subst_redexp subst (out_gen globwit_red_expr x))
+ | TacticArgType ->
+ in_gen globwit_tactic (subst_tactic subst (out_gen globwit_tactic x))
+ | CastedOpenConstrArgType ->
+ in_gen globwit_casted_open_constr
+ (subst_rawconstr subst (out_gen globwit_casted_open_constr x))
+ | ConstrWithBindingsArgType ->
+ in_gen globwit_constr_with_bindings
+ (subst_raw_with_bindings subst (out_gen globwit_constr_with_bindings x))
+ | List0ArgType _ -> app_list0 (subst_genarg subst) x
+ | List1ArgType _ -> app_list1 (subst_genarg subst) x
+ | OptArgType _ -> app_opt (subst_genarg subst) x
+ | PairArgType _ -> app_pair (subst_genarg subst) (subst_genarg subst) x
+ | ExtraArgType s -> lookup_genarg_subst s subst x
+
+(***************************************************************************)
+(* Tactic registration *)
(* For bad tactic calls *)
let bad_tactic_args s =
@@ -1651,10 +2041,15 @@ let cache_md (_,defs) =
List.iter (fun (sp,_) -> Nametab.push_tactic (Until 1) sp) defs;
List.iter add (List.map register_tacdef defs)
+let subst_md (_,subst,defs) =
+ List.map (fun (sp,t) -> (sp,subst_tactic subst t)) defs
+
let (inMD,outMD) =
declare_object {(default_object "TAC-DEFINITION") with
cache_function = cache_md;
open_function = (fun i o -> if i=1 then cache_md o);
+ subst_function = subst_md;
+ classify_function = (fun (_,o) -> Substitute o);
export_function = (fun x -> Some x)}
(* Adds a definition for tactics in the table *)
@@ -1666,18 +2061,42 @@ let make_absolute_name (loc,id) =
++ pr_sp sp);
sp
+let make_empty_glob_sign () =
+ { ltacvars = ([],[]); ltacrecvars = [];
+ metavars = []; gsigma = Evd.empty; genv = Global.env() }
+
let add_tacdef isrec tacl =
- let lfun = List.map (fun ((loc,id),_) -> id) tacl in
- let ist = ((if isrec then lfun else []), [], Evd.empty, Global.env()) in
- let tacl = List.map (fun (id,tac) -> (make_absolute_name id,tac)) tacl in
- let tacl = List.map (fun (id,def) -> (id,glob_tactic ist def)) tacl in
- let _ = Lib.add_leaf (List.hd lfun) (inMD tacl) in
+ let rfun = List.map (fun ((loc,id as locid),_) -> (id,make_absolute_name locid)) tacl in
+ let ist =
+ {(make_empty_glob_sign()) with ltacrecvars = if isrec then rfun else []} in
+ let gtacl =
+ List.map2 (fun (_,sp) (_,def) ->
+ (sp,Options.with_option strict_check (intern_tactic ist) def))
+ rfun tacl in
+ let id0 = fst (List.hd rfun) in
+ let _ = Lib.add_leaf id0 (inMD gtacl) in
List.iter
- (fun id -> Options.if_verbose msgnl (pr_id id ++ str " is defined")) lfun
+ (fun (id,_) -> Options.if_verbose msgnl (pr_id id ++ str " is defined"))
+ rfun
+
+(***************************************************************************)
+(* Other entry points *)
+
+let glob_tactic x = intern_tactic (make_empty_glob_sign ()) x
let interp_redexp env evc r =
let ist = { lfun=[]; lmatch=[]; debug=get_debug () } in
- redexp_interp ist evc env r
-
-let _ = Auto.set_extern_interp (fun l -> tac_interp [] l (get_debug()))
-let _ = Dhyp.set_extern_interp interp
+ let gist = {(make_empty_glob_sign ()) with genv = env; gsigma = evc } in
+ redexp_interp ist evc env (intern_redexp gist r)
+
+(***************************************************************************)
+(* Backwarding recursive needs of tactic glob/interp/eval functions *)
+
+let _ = Auto.set_extern_interp
+ (fun l -> interp_tactic {lfun=[];lmatch=l;debug=get_debug()})
+let _ = Auto.set_extern_intern_tac
+ (fun l -> intern_tactic {(make_empty_glob_sign()) with metavars=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)