diff options
author | herbelin <herbelin@85f007b7-540e-0410-9357-904b9bb8a0f7> | 2002-05-29 10:48:22 +0000 |
---|---|---|
committer | herbelin <herbelin@85f007b7-540e-0410-9357-904b9bb8a0f7> | 2002-05-29 10:48:22 +0000 |
commit | 1e5182e9d5c29ae9adeed20dae32969785758809 (patch) | |
tree | 834e85bb904f24fa3e1a48176456eeb2c523bb5f | |
parent | b5011fe9c8b410074f2b1299cf83aabed834601f (diff) |
Réorganisation des tclTHEN (cf dev/changements.txt)
git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/coq/trunk@2721 85f007b7-540e-0410-9357-904b9bb8a0f7
-rw-r--r-- | proofs/proof_trees.ml | 66 | ||||
-rw-r--r-- | proofs/proof_trees.mli | 2 | ||||
-rw-r--r-- | proofs/proof_type.ml | 80 | ||||
-rw-r--r-- | proofs/proof_type.mli | 77 | ||||
-rw-r--r-- | proofs/refiner.ml | 169 | ||||
-rw-r--r-- | proofs/refiner.mli | 65 | ||||
-rw-r--r-- | tactics/tacticals.ml | 91 | ||||
-rw-r--r-- | tactics/tacticals.mli | 32 |
8 files changed, 323 insertions, 259 deletions
diff --git a/proofs/proof_trees.ml b/proofs/proof_trees.ml index 7c5152672..0c916495a 100644 --- a/proofs/proof_trees.ml +++ b/proofs/proof_trees.ml @@ -23,9 +23,11 @@ open Tacred open Typing open Nametab +(* let is_bind = function - | Bindings _ -> true + | Tacexpr.Cbindings _ -> true | _ -> false +*) (* Functions on goals *) @@ -48,10 +50,9 @@ let children_of_proof pf = let goal_of_proof pf = pf.goal -let subproof_of_proof pf = - match pf.subproof with - | None -> failwith "subproof_of_proof" - | Some pf -> pf +let subproof_of_proof pf = match pf.ref with + | Some (Tactic (_,pf), _) -> pf + | _ -> failwith "subproof_of_proof" let status_of_proof pf = pf.status @@ -59,7 +60,9 @@ let is_complete_proof pf = pf.status = Complete_proof let is_leaf_proof pf = (pf.ref = None) -let is_tactic_proof pf = (pf.subproof <> None) +let is_tactic_proof pf = match pf.ref with + | Some (Tactic _, _) -> true + | _ -> false (*******************************************************************) @@ -245,21 +248,24 @@ let pr_subgoals_existential sigma = function v 0 (int(List.length rest+1) ++ str" subgoals" ++ cut () ++ pg1 ++ prest ++ fnl ()) +(* open Ast open Termast +open Tacexpr +open Rawterm let ast_of_cvt_bind f = function - | (NoDep n,c) -> ope ("BINDING", [(num n); ope ("COMMAND",[(f c)])]) - | (Dep id,c) -> ope ("BINDING", [nvar id; ope ("COMMAND",[(f c)])]) - | (Com,c) -> ope ("BINDING", [ope ("COMMAND",[(f c)])]) + | (NoDepBinding n,c) -> ope ("BINDING", [(num n); ope ("CONSTR",[(f c)])]) + | (DepBinding id,c) -> ope ("BINDING", [nvar id; ope ("CONSTR",[(f c)])]) + | (AnonymousBinding,c) -> ope ("BINDING", [ope ("CONSTR",[(f c)])]) let rec ast_of_cvt_intro_pattern = function | WildPat -> ope ("WILDCAR",[]) | IdPat id -> nvar id - | DisjPat l -> ope ("DISJPATTERN", (List.map ast_of_cvt_intro_pattern l)) +(* | DisjPat l -> ope ("DISJPATTERN", (List.map ast_of_cvt_intro_pattern l))*) | ConjPat l -> ope ("CONJPATTERN", (List.map ast_of_cvt_intro_pattern l)) - | ListPat l -> ope ("LISTPATTERN", (List.map ast_of_cvt_intro_pattern l)) - +*) +(* (* Gives the ast list corresponding to a reduction flag *) open RedFlags @@ -280,14 +286,19 @@ let last_of_cvt_flags red = else [ope("Delta",[]);ope("Unf",lqid)])@ (if (red_set red fIOTA) then [ope("Iota",[])] else []) - +*) +(* (* Gives the ast corresponding to a reduction expression *) +open Rawterm + let ast_of_cvt_redexp = function | Red _ -> ope ("Red",[]) | Hnf -> ope("Hnf",[]) | Simpl -> ope("Simpl",[]) +(* | Cbv flg -> ope("Cbv",last_of_cvt_flags flg) | Lazy flg -> ope("Lazy",last_of_cvt_flags flg) +*) | Unfold l -> ope("Unfold",List.map (fun (locc,sp) -> ope("UNFOLD", [match sp with @@ -297,24 +308,27 @@ let ast_of_cvt_redexp = function (shortest_qualid_of_global (Global.env()) (ConstRef sp))] @(List.map num locc))) l) | Fold l -> - ope("Fold",List.map (fun c -> ope ("COMMAND", + ope("Fold",List.map (fun c -> ope ("CONSTR", [ast_of_constr false (Global.env ()) c])) l) | Pattern l -> - ope("Pattern",List.map (fun (locc,csr,_) -> ope("PATTERN", - [ope ("COMMAND",[ast_of_constr false (Global.env ()) csr])]@ + ope("Pattern",List.map (fun (locc,csr) -> ope("PATTERN", + [ope ("CONSTR",[ast_of_constr false (Global.env ()) csr])]@ (List.map num locc))) l) - +*) (* Gives the ast corresponding to a tactic argument *) +(* let ast_of_cvt_arg = function | Identifier id -> nvar id +(* | Qualid qid -> ast_of_qualid qid +*) | Quoted_string s -> string s | Integer n -> num n - | Command c -> ope ("COMMAND",[c]) +(* | Command c -> ope ("CONSTR",[c])*) | Constr c -> - ope ("COMMAND",[ast_of_constr false (Global.env ()) c]) + ope ("CONSTR",[ast_of_constr false (Global.env ()) c]) | OpenConstr (_,c) -> - ope ("COMMAND",[ast_of_constr false (Global.env ()) c]) + ope ("CONSTR",[ast_of_constr false (Global.env ()) c]) | Constr_context _ -> anomalylabstrm "ast_of_cvt_arg" (str "Constr_context argument could not be used") @@ -323,6 +337,7 @@ let ast_of_cvt_arg = function | InHyp id -> ope ("INHYP", [nvar id]) | InHypType id -> ope ("INHYPTYPE", [nvar id]) in ope ("CLAUSE", List.map transl idl) +(* | Bindings bl -> ope ("BINDINGS", List.map (ast_of_cvt_bind (fun x -> x)) bl) | Cbindings bl -> @@ -330,12 +345,15 @@ let ast_of_cvt_arg = function List.map (ast_of_cvt_bind (ast_of_constr false (Global.env ()))) bl) +*) +(* TODO | Tacexp ast -> ope ("TACTIC",[ast]) | Tac (tac,ast) -> ast +*) | Redexp red -> ope("REDEXP",[ast_of_cvt_redexp red]) - | Fixexp (id,n,c) -> ope ("FIXEXP",[nvar id; num n; ope ("COMMAND",[c])]) - | Cofixexp (id,c) -> ope ("COFIXEXP",[nvar id; ope ("COMMAND",[c])]) - | Intropattern p -> ast_of_cvt_intro_pattern p + | Fixexp (id,n,c) -> ope ("FIXEXP",[nvar id; num n; ope ("CONSTR",[ast_of_constr false (Global.env ()) c])]) + | Cofixexp (id,c) -> ope ("COFIXEXP",[nvar id; ope ("CONSTR",[ast_of_constr false (Global.env ()) c])]) +(* | Intropattern p -> ast_of_cvt_intro_pattern p*) | Letpatterns (gl_occ_opt,hyp_occ_list) -> let hyps_pats = List.map @@ -347,4 +365,4 @@ let ast_of_cvt_arg = function | None -> hyps_pats | Some l -> hyps_pats @ [ope ("CCLPATTERN", List.map num l)] in ope ("LETPATTERNS", all_pats) - +*) diff --git a/proofs/proof_trees.mli b/proofs/proof_trees.mli index d6a1a51d5..889c16aba 100644 --- a/proofs/proof_trees.mli +++ b/proofs/proof_trees.mli @@ -67,4 +67,6 @@ val pr_evars_int : int -> (int * goal) list -> std_ppcmds val pr_subgoals_existential : evar_map -> goal list -> std_ppcmds (* Gives the ast corresponding to a tactic argument *) +(* val ast_of_cvt_arg : tactic_arg -> Coqast.t +*) diff --git a/proofs/proof_type.ml b/proofs/proof_type.ml index afee5e2a9..c9f8aca31 100644 --- a/proofs/proof_type.ml +++ b/proofs/proof_type.ml @@ -5,32 +5,27 @@ (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (***********************************************************************) + +(*i $Id$ *) + (*i*) open Environ open Evd open Names open Term open Util +open Tacexpr +open Rawterm +open Genarg (*i*) (* This module defines the structure of proof tree and the tactic type. So, it is used by Proof_tree and Refiner *) -type bindOcc = - | Dep of identifier - | NoDep of int - | Com - -type 'a substitution = (bindOcc * 'a) list - type pf_status = | Complete_proof | Incomplete_proof -type hyp_location = (* To distinguish body and type of local defs *) - | InHyp of identifier - | InHypType of identifier - type prim_rule = | Intro of identifier | Intro_replacing of identifier @@ -61,12 +56,11 @@ type 'a sigma = { type proof_tree = { status : pf_status; goal : goal; - ref : (rule * proof_tree list) option; - subproof : proof_tree option } + ref : (rule * proof_tree list) option } and rule = | Prim of prim_rule - | Tactic of tactic_expression + | Tactic of tactic_expr * proof_tree | Change_evars and goal = evar_info @@ -75,31 +69,35 @@ and tactic = goal sigma -> (goal list sigma * validation) and validation = (proof_tree list -> proof_tree) +and tactic_expr = + (constr, + Closure.evaluable_global_reference, + inductive or_metanum, + identifier) + Tacexpr.gen_tactic_expr + +and atomic_tactic_expr = + (constr, + Closure.evaluable_global_reference, + inductive or_metanum, + identifier) + Tacexpr.gen_atomic_tactic_expr + and tactic_arg = - | Command of Coqast.t - | Constr of constr - | OpenConstr of Pretyping.open_constr - | Constr_context of constr - | Identifier of identifier - | Qualid of Nametab.qualid - | Integer of int - | Clause of hyp_location list - | Bindings of Coqast.t substitution - | Cbindings of constr substitution - | Quoted_string of string - | Tacexp of Coqast.t - | Tac of tactic * Coqast.t - | Redexp of Tacred.red_expr - | Fixexp of identifier * int * Coqast.t - | Cofixexp of identifier * Coqast.t - | Letpatterns of (int list option * (identifier * int list) list) - | Intropattern of intro_pattern - -and intro_pattern = - | WildPat - | IdPat of identifier - | DisjPat of intro_pattern list - | ConjPat of intro_pattern list - | ListPat of intro_pattern list - -and tactic_expression = string * tactic_arg list + (constr, + Closure.evaluable_global_reference, + inductive or_metanum, + identifier) + Tacexpr.gen_tactic_arg + +type hyp_location = identifier Tacexpr.raw_hyp_location + +type open_generic_argument = + (constr,raw_tactic_expr) generic_argument +type closed_generic_argument = + (constr,raw_tactic_expr) generic_argument + +type 'a closed_abstract_argument_type = + ('a,constr,raw_tactic_expr) abstract_argument_type + +type declaration_hook = Nametab.strength -> Nametab.global_reference -> unit diff --git a/proofs/proof_type.mli b/proofs/proof_type.mli index 60cd71092..b6a08ac8b 100644 --- a/proofs/proof_type.mli +++ b/proofs/proof_type.mli @@ -14,26 +14,18 @@ open Evd open Names open Term open Util +open Tacexpr +open Rawterm +open Genarg (*i*) (* This module defines the structure of proof tree and the tactic type. So, it is used by [Proof_tree] and [Refiner] *) -type bindOcc = - | Dep of identifier - | NoDep of int - | Com - -type 'a substitution = (bindOcc * 'a) list - type pf_status = | Complete_proof | Incomplete_proof -type hyp_location = (* To distinguish body and type of local defs *) - | InHyp of identifier - | InHypType of identifier - type prim_rule = | Intro of identifier | Intro_replacing of identifier @@ -92,12 +84,11 @@ type 'a sigma = { type proof_tree = { status : pf_status; goal : goal; - ref : (rule * proof_tree list) option; - subproof : proof_tree option } + ref : (rule * proof_tree list) option } and rule = | Prim of prim_rule - | Tactic of tactic_expression + | Tactic of tactic_expr * proof_tree | Change_evars and goal = evar_info @@ -106,31 +97,35 @@ and tactic = goal sigma -> (goal list sigma * validation) and validation = (proof_tree list -> proof_tree) +and tactic_expr = + (constr, + Closure.evaluable_global_reference, + inductive or_metanum, + identifier) + Tacexpr.gen_tactic_expr + +and atomic_tactic_expr = + (constr, + Closure.evaluable_global_reference, + inductive or_metanum, + identifier) + Tacexpr.gen_atomic_tactic_expr + and tactic_arg = - | Command of Coqast.t - | Constr of constr - | OpenConstr of Pretyping.open_constr - | Constr_context of constr - | Identifier of identifier - | Qualid of Nametab.qualid - | Integer of int - | Clause of hyp_location list - | Bindings of Coqast.t substitution - | Cbindings of constr substitution - | Quoted_string of string - | Tacexp of Coqast.t - | Tac of tactic * Coqast.t - | Redexp of Tacred.red_expr - | Fixexp of identifier * int * Coqast.t - | Cofixexp of identifier * Coqast.t - | Letpatterns of (int list option * (identifier * int list) list) - | Intropattern of intro_pattern - -and intro_pattern = - | WildPat - | IdPat of identifier - | DisjPat of intro_pattern list - | ConjPat of intro_pattern list - | ListPat of intro_pattern list - -and tactic_expression = string * tactic_arg list + (constr, + Closure.evaluable_global_reference, + inductive or_metanum, + identifier) + Tacexpr.gen_tactic_arg + +type hyp_location = identifier Tacexpr.raw_hyp_location + +type open_generic_argument = + (constr,raw_tactic_expr) generic_argument +type closed_generic_argument = + (constr,raw_tactic_expr) generic_argument + +type 'a closed_abstract_argument_type = + ('a,constr,raw_tactic_expr) abstract_argument_type + +type declaration_hook = Nametab.strength -> Nametab.global_reference -> unit diff --git a/proofs/refiner.ml b/proofs/refiner.ml index 7937b9913..b990e6f4b 100644 --- a/proofs/refiner.ml +++ b/proofs/refiner.ml @@ -22,6 +22,7 @@ open Type_errors open Proof_trees open Proof_type open Logic +open Printer type transformation_tactic = proof_tree -> (goal list * validation) @@ -98,7 +99,6 @@ let rec frontier p = (fun retpfl -> let pfl' = mapshape (List.map List.length gll) vl retpfl in { status = and_status (List.map pf_status pfl'); - subproof = p.subproof; goal = p.goal; ref = Some(r,pfl')})) @@ -120,7 +120,6 @@ let rec nb_unsolved_goals pf = let leaf g = { status = Incomplete_proof; - subproof = None; goal = g; ref = None } @@ -130,8 +129,8 @@ let tac_tab = Hashtbl.create 17 let add_tactic s t = if Hashtbl.mem tac_tab s then - errorlabstrm ("Refiner.add_tactic: "^s) - (str "Cannot redeclare a tactic."); + errorlabstrm ("Refiner.add_tactic: ") + (str ("Cannot redeclare tactic "^s)); Hashtbl.add tac_tab s t let overwriting_add_tactic s t = @@ -158,6 +157,16 @@ let check_subproof_connection gl spfl = if not (list_for_all2eq (fun g pf -> g=pf.goal) gl spfl) then (bad_subproof (); false) else true +let abstract_tactic_expr te tacfun gls = + let (sgl_sigma,v) = tacfun gls in + let hidden_proof = v (List.map leaf sgl_sigma.it) in + (sgl_sigma, + fun spfl -> + assert (check_subproof_connection sgl_sigma.it spfl); + { status = and_status (List.map pf_status spfl); + goal = gls.it; + ref = Some(Tactic(te,hidden_proof),spfl) }) + let refiner = function | Prim pr as r -> let prim_fun = prim_refiner pr in @@ -168,21 +177,9 @@ let refiner = function assert (check_subproof_connection sgl spfl); { status = and_status (List.map pf_status spfl); goal = goal_sigma.it; - subproof = None; ref = Some(r,spfl) }))) - - | Tactic(s,targs) as r -> - let tacfun = lookup_tactic s targs in - (fun goal_sigma -> - let (sgl_sigma,v) = tacfun goal_sigma in - let hidden_proof = v (List.map leaf sgl_sigma.it) in - (sgl_sigma, - fun spfl -> - assert (check_subproof_connection sgl_sigma.it spfl); - { status = and_status (List.map pf_status spfl); - goal = goal_sigma.it; - subproof = Some hidden_proof; - ref = Some(r,spfl) })) + + | Tactic _ -> failwith "Refiner: should not occur" (* [Local_constraints lc] makes the local constraints be [lc] and normalizes evars *) @@ -197,7 +194,6 @@ let refiner = function assert (check_subproof_connection [ngl] spfl); { status = (List.hd spfl).status; goal = gl; - subproof = None; ref = Some(r,spfl) })) (* if the evar change does not affect the goal, leave the proof tree unchanged *) @@ -206,9 +202,22 @@ let refiner = function assert (List.length spfl = 1); List.hd spfl)))) -let vernac_tactic texp = refiner (Tactic texp) let norm_evar_tac gl = refiner Change_evars gl +(* +let vernac_tactic (s,args) = + let tacfun = lookup_tactic s args in + abstract_extra_tactic s args tacfun +*) +let abstract_tactic te = abstract_tactic_expr (Tacexpr.TacAtom (dummy_loc,te)) + +let abstract_extended_tactic s args = + abstract_tactic (Tacexpr.TacExtend (s, args)) + +let vernac_tactic (s,args) = + let tacfun = lookup_tactic s args in + abstract_extended_tactic s args tacfun + (* [rc_of_pfsigma : proof sigma -> readable_constraints] *) let rc_of_pfsigma sigma = rc_of_gc sigma.sigma sigma.it.goal @@ -228,7 +237,7 @@ let extract_open_proof sigma pf = let rec proof_extractor vl = function | {ref=Some(Prim _,_)} as pf -> prim_extractor proof_extractor vl pf - | {ref=Some(Tactic _,spfl); subproof=Some hidden_proof} -> + | {ref=Some(Tactic (_,hidden_proof),spfl)} -> let sgl,v = frontier hidden_proof in let flat_proof = v spfl in proof_extractor vl flat_proof @@ -304,20 +313,37 @@ let start_tac gls = let finish_tac (sigr,gl,p) = (repackage sigr gl, p) -let thens_tac tac2l taci (sigr,gs,p) = - let (gl,gi) = - try list_chop (List.length tac2l) gs - with Failure _ -> errorlabstrm "Refiner.combine_tactics" - (str "Wrong number of tactics.") in - let tac2gl = - List.combine gl tac2l @ list_map_i (fun i g -> (g, taci i)) 1 gi in +(* Apply [taci.(i)] on the first n-th subgoals and [tac] on the others *) +let thensf_tac taci tac (sigr,gs,p) = + let n = Array.length taci in + let nsg = List.length gs in + if nsg<n then errorlabstrm "Refiner.thensn_tac" (str "Not enough subgoals."); + let gll,pl = + List.split + (list_map_i (fun i -> apply_sig_tac sigr (if i<n then taci.(i) else tac)) + 0 gs) in + (sigr, List.flatten gll, + compose p (mapshape (List.map List.length gll) pl)) + +(* Apply [taci.(i)] on the last n-th subgoals and [tac] on the others *) +let thensl_tac tac taci (sigr,gs,p) = + let n = Array.length taci in + let nsg = List.length gs in + if nsg<n then errorlabstrm "Refiner.thensn_tac" (str "Not enough subgoals."); let gll,pl = - List.split(List.map (fun (g,tac2) -> apply_sig_tac sigr tac2 g) tac2gl) in + List.split + (list_map_i (fun i -> apply_sig_tac sigr (if i<0 then tac else taci.(i))) + (n-nsg) gs) in (sigr, List.flatten gll, compose p (mapshape (List.map List.length gll) pl)) -let then_tac tac = thens_tac [] (fun _ -> tac) +(* Apply [tac i] on the ith subgoal (no subgoals number check) *) +let thensi_tac tac (sigr,gs,p) = + let gll,pl = + List.split (list_map_i (fun i -> apply_sig_tac sigr (tac i)) 1 gs) in + (sigr, List.flatten gll, compose p (mapshape (List.map List.length gll) pl)) +let then_tac tac = thensf_tac [||] tac let non_existent_goal n = errorlabstrm ("No such goal: "^(string_of_int n)) @@ -330,42 +356,53 @@ let theni_tac i tac ((_,gl,_) as subgoals) = let k = if i < 0 then nsg + i + 1 else i in if nsg < 1 then errorlabstrm "theni_tac" (str"No more subgoals.") else if k >= 1 & k <= nsg then - thens_tac [] (fun i -> if i = k then tac else tclIDTAC) subgoals + thensf_tac + (Array.init k (fun i -> if i+1 = k then tac else tclIDTAC)) tclIDTAC + subgoals else non_existent_goal k -(* [tclTHENSi tac1 [t1 ; ... ; tn] taci gls] applies the tactic [tac1] +(* [tclTHENSFIRSTn tac1 [|t1 ; ... ; tn|] tac2 gls] applies the tactic [tac1] to [gls] and applies [t1], ..., [tn] to the [n] first resulting - subgoals, and [(taci i)] to the (i+n)-th goal. Raises an error if - the number of resulting subgoals is less than [n] *) -let tclTHENSi tac1 tac2l taci gls = - finish_tac (thens_tac tac2l taci (then_tac tac1 (start_tac gls))) - + subgoals, and [tac2] to the others subgoals. Raises an error if + the number of resulting subgoals is strictly less than [n] *) +let tclTHENSFIRSTn tac1 taci tac gls = + finish_tac (thensf_tac taci tac (then_tac tac1 (start_tac gls))) + +(* [tclTHENSLASTn tac1 tac2 [|t1 ;...; tn|] gls] applies the tactic [tac1] + to [gls] and applies [t1], ..., [tn] to the [n] last resulting + subgoals, and [tac2] to the other subgoals. Raises an error if the + number of resulting subgoals is strictly less than [n] *) +let tclTHENSLASTn tac1 tac taci gls = + finish_tac (thensl_tac tac taci (then_tac tac1 (start_tac gls))) + +(* [tclTHEN_i tac taci gls] applies the tactic [tac] to [gls] and applies + [(taci i)] to the i_th resulting subgoal (starting from 1), whatever the + number of subgoals is *) +let tclTHEN_i tac taci gls = + finish_tac (thensi_tac taci (then_tac tac (start_tac gls))) + +let tclTHENLASTn tac1 taci = tclTHENSLASTn tac1 tclIDTAC taci +let tclTHENFIRSTn tac1 taci = tclTHENSFIRSTn tac1 taci tclIDTAC (* [tclTHEN tac1 tac2 gls] applies the tactic [tac1] to [gls] and applies [tac2] to every resulting subgoals *) -let tclTHEN tac1 tac2 = tclTHENSi tac1 [] (fun _ -> tac2) +let tclTHEN tac1 tac2 = tclTHENSFIRSTn tac1 [||] tac2 -(* [tclTHEN_i tac1 tac2 gls] applies the tactic [tac1] to [gls] and applies - [(tac2 i)] to the i_th resulting subgoal (starting from 1) *) -let tclTHEN_i tac1 tac2 = tclTHENSi tac1 [] tac2 - -(* [tclTHENS tac1 [t1 ; ... ; tn] gls] applies the tactic [tac1] to +(* [tclTHENSV tac1 [t1 ; ... ; tn] gls] applies the tactic [tac1] to [gls] and applies [t1],..., [tn] to the [n] resulting subgoals. Raises an error if the number of resulting subgoals is not [n] *) -let tclTHENS tac1 tac2l = - tclTHENSi tac1 tac2l (fun _ -> tclFAIL_s "Wrong number of tactics.") - -(* Same as [tclTHENS] but completes with [tac3] if the number resulting - subgoals is strictly less than [n] *) -let tclTHENST tac1 tac2l tac3 = tclTHENSi tac1 tac2l (fun _ -> tac3) +let tclTHENSV tac1 tac2v = + tclTHENSFIRSTn tac1 tac2v (tclFAIL_s "Wrong number of tactics.") -(* Same as tclTHENST but completes with [Idtac] *) -let tclTHENSI tac1 tac2l = tclTHENST tac1 tac2l tclIDTAC +let tclTHENS tac1 tac2l = tclTHENSV tac1 (Array.of_list tac2l) -(* [tclTHENL tac1 tac2 gls] applies the tactic [tac1] to [gls] and [tac2] +(* [tclTHENLAST tac1 tac2 gls] applies the tactic [tac1] to [gls] and [tac2] to the last resulting subgoal *) -let tclTHENL (tac1 : tactic) (tac2 : tactic) (gls : goal sigma) = - finish_tac (theni_tac (-1) tac2 (then_tac tac1 (start_tac gls))) +let tclTHENLAST tac1 tac2 = tclTHENSLASTn tac1 tclIDTAC [|tac2|] + +(* [tclTHENFIRST tac1 tac2 gls] applies the tactic [tac1] to [gls] and [tac2] + to the first resulting subgoal *) +let tclTHENFIRST tac1 tac2 = tclTHENSFIRSTn tac1 [|tac2|] tclIDTAC (* [tclTHENLIST [t1;..;tn]] applies [t1] then [t2] ... then [tn]. More @@ -473,7 +510,7 @@ let rec tclREPEAT t g = let tclAT_LEAST_ONCE t = (tclTHEN t (tclREPEAT t)) -(* Repeat on the first subgoal *) +(* Repeat on the first subgoal (no failure if no more subgoal) *) let rec tclREPEAT_MAIN t g = (tclORELSE (tclTHEN_i t (fun i -> if i = 1 then (tclREPEAT_MAIN t) else tclIDTAC)) tclIDTAC) g @@ -590,7 +627,6 @@ let descend n p = let newstatus = and_status (List.map pf_status spfl) in { status = newstatus; goal = p.goal; - subproof = p.subproof; ref = Some(r,spfl) } else error "descend: validation")) @@ -607,13 +643,13 @@ let traverse n pts = match n with tstack = tl; tpfsigma = pts.tpfsigma }) | -1 -> (* go to the hidden tactic-proof, if any, otherwise fail *) - (match pts.tpf.subproof with - | None -> error "traverse: not a tactic-node" - | Some spf -> + (match pts.tpf.ref with + | Some (Tactic (_,spf),_) -> let v = (fun pfl -> pts.tpf) in { tpf = spf; tstack = (-1,v)::pts.tstack; - tpfsigma = pts.tpfsigma }) + tpfsigma = pts.tpfsigma } + | _ -> error "traverse: not a tactic-node") | n -> (* when n>0, go to the nth child *) let (npf,v) = descend n pts.tpf in { tpf = npf; @@ -782,14 +818,15 @@ let rec top_of_tree pts = (* Pretty-printers. *) open Pp -open Printer -let pr_tactic (s,l) = - gentacpr (Ast.ope (s,(List.map ast_of_cvt_arg l))) +let pr_tactic = function + | Tacexpr.TacArg (Tacexpr.Tacexp t) -> + Pptactic.pr_raw_tactic t (*top tactic from tacinterp*) + | t -> Pptactic.pr_tactic t let pr_rule = function | Prim r -> pr_prim_rule r - | Tactic texp -> hov 0 (pr_tactic texp) + | Tactic (texp,_) -> hov 0 (pr_tactic texp) | Change_evars -> (* This is internal tactic and cannot be replayed at user-level. Function pr_rule_dot below is used when we want to hide @@ -798,8 +835,8 @@ let pr_rule = function (* Does not print change of evars *) let pr_rule_dot = function - | Change_evars -> (mt ()) - | r -> (pr_rule r ++ str"." ++ fnl ()) + | Change_evars -> mt () + | r -> pr_rule r ++ str"." ++ fnl () exception Different diff --git a/proofs/refiner.mli b/proofs/refiner.mli index 385d6e8b1..34f8fb665 100644 --- a/proofs/refiner.mli +++ b/proofs/refiner.mli @@ -1,3 +1,4 @@ + (***********************************************************************) (* v * The Coq Proof Assistant / The Coq Development Team *) (* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *) @@ -14,6 +15,7 @@ open Sign open Evd open Proof_trees open Proof_type +open Tacexpr (*i*) (* The refiner (handles primitive rules and high-level tactics). *) @@ -30,12 +32,20 @@ val apply_sig_tac : type transformation_tactic = proof_tree -> (goal list * validation) -val add_tactic : string -> (tactic_arg list -> tactic) -> unit -val overwriting_add_tactic : string -> (tactic_arg list -> tactic) -> unit -val lookup_tactic : string -> (tactic_arg list) -> tactic +val add_tactic : string -> (closed_generic_argument list -> tactic) -> unit +val overwriting_add_tactic : string -> (closed_generic_argument list -> tactic) -> unit +val lookup_tactic : string -> (closed_generic_argument list) -> tactic + +(*s Hiding the implementation of tactics. *) + +(* [abstract_tactic tac] hides the (partial) proof produced by [tac] under + a single proof node *) +val abstract_tactic : atomic_tactic_expr -> tactic -> tactic +val abstract_tactic_expr : tactic_expr -> tactic -> tactic +val abstract_extended_tactic : string -> closed_generic_argument list -> tactic -> tactic val refiner : rule -> tactic -val vernac_tactic : tactic_expression -> tactic +val vernac_tactic : string * closed_generic_argument list -> tactic val frontier : transformation_tactic val list_pf : proof_tree -> goal list val unTAC : tactic -> goal sigma -> proof_tree sigma @@ -57,24 +67,44 @@ val tclTHENLIST : tactic list -> tactic [(tac2 i)] to the [i]$^{th}$ resulting subgoal (starting from 1) *) val tclTHEN_i : tactic -> (int -> tactic) -> tactic -(* [tclTHENL tac1 tac2 gls] applies the tactic [tac1] to [gls] and [tac2] - to the last resulting subgoal *) -val tclTHENL : tactic -> tactic -> tactic +(* [tclTHENLAST tac1 tac2 gls] applies the tactic [tac1] to [gls] and [tac2] + to the last resulting subgoal (previously called [tclTHENL]) *) +val tclTHENLAST : tactic -> tactic -> tactic + +(* [tclTHENFIRST tac1 tac2 gls] applies the tactic [tac1] to [gls] and [tac2] + to the first resulting subgoal *) +val tclTHENFIRST : tactic -> tactic -> tactic -(* [tclTHENS tac1 [t1 ; ... ; tn] gls] applies the tactic [tac1] to +(* [tclTHENS tac1 [|t1 ; ... ; tn|] gls] applies the tactic [tac1] to [gls] and applies [t1],..., [tn] to the [n] resulting subgoals. Raises an error if the number of resulting subgoals is not [n] *) +val tclTHENSV : tactic -> tactic array -> tactic + +(* Same with a list of tactics *) val tclTHENS : tactic -> tactic list -> tactic -(* Same as [tclTHENS] but completes with [tac3] if the number resulting - subgoals is strictly more than [n] *) -val tclTHENST : tactic -> tactic list -> tactic -> tactic +(* [tclTHENST] is renamed [tclTHENSFIRSTn] +val tclTHENST : tactic -> tactic array -> tactic -> tactic +*) + +(* [tclTHENSLASTn tac1 [t1 ; ... ; tn] tac2 gls] applies [t1],...,[tn] on the + last [n] resulting subgoals and [tac2] on the remaining first subgoals *) +val tclTHENSLASTn : tactic -> tactic -> tactic array -> tactic -(* Same as [tclTHENS] but completes with [tac3 i] *) -val tclTHENSi : tactic -> tactic list -> (int -> tactic) -> tactic +(* [tclTHENSFIRSTn tac1 [t1 ; ... ; tn] tac2 gls] first applies [tac1], then + applies [t1],...,[tn] on the first [n] resulting subgoals and + [tac2] for the remaining last subgoals (previously called tclTHENST) *) +val tclTHENSFIRSTn : tactic -> tactic array -> tactic -> tactic -(* Same as tclTHENST but completes with [Idtac] *) -val tclTHENSI : tactic -> tactic list -> tactic +(* [tclTHENLASTn tac1 [t1 ; ... ; tn] gls] first applies [tac1] then, + applies [t1],...,[tn] on the last [n] resulting subgoals and leaves + unchanged the other subgoals *) +val tclTHENLASTn : tactic -> tactic array -> tactic + +(* [tclTHENFIRSTn tac1 [t1 ; ... ; tn] gls] first applies [tac1] then, + applies [t1],...,[tn] on the first [n] resulting subgoals and leaves + unchanged the other subgoals (previously called [tclTHENSI]) *) +val tclTHENFIRSTn : tactic -> tactic array -> tactic (* A special exception for levels for the Fail tactic *) exception FailError of int @@ -95,7 +125,6 @@ val tclWEAK_PROGRESS : tactic -> tactic val tclNOTSAMEGOAL : tactic -> tactic val tclINFO : tactic -> tactic - (*s Tactics handling a list of goals. *) type validation_list = proof_tree list -> proof_tree list @@ -152,8 +181,8 @@ open Pp (*i*) val print_proof : evar_map -> named_context -> proof_tree -> std_ppcmds -val pr_rule : rule -> std_ppcmds -val pr_tactic : tactic_expression -> std_ppcmds +val pr_rule : rule -> std_ppcmds +val pr_tactic : tactic_expr -> std_ppcmds val print_script : bool -> evar_map -> named_context -> proof_tree -> std_ppcmds val print_treescript : diff --git a/tactics/tacticals.ml b/tactics/tacticals.ml index 238dd4b95..b6fea7dc2 100644 --- a/tactics/tacticals.ml +++ b/tactics/tacticals.ml @@ -19,6 +19,7 @@ open Inductive open Reduction open Environ open Declare +open Refiner open Tacmach open Clenv open Pattern @@ -29,24 +30,39 @@ open Wcclausenv (* Basic Tacticals *) (******************************************) -let tclIDTAC = Tacmach.tclIDTAC -let tclORELSE = Tacmach.tclORELSE -let tclTHEN = Tacmach.tclTHEN -let tclTHEN_i = Tacmach.tclTHEN_i -let tclTHENL = Tacmach.tclTHENL -let tclTHENS = Tacmach.tclTHENS -let tclTHENSi = Tacmach.tclTHENSi -let tclREPEAT = Tacmach.tclREPEAT -let tclFIRST = Tacmach.tclFIRST -let tclSOLVE = Tacmach.tclSOLVE -let tclTRY = Tacmach.tclTRY -let tclINFO = Tacmach.tclINFO -let tclCOMPLETE = Tacmach.tclCOMPLETE -let tclAT_LEAST_ONCE = Tacmach.tclAT_LEAST_ONCE -let tclFAIL = Tacmach.tclFAIL -let tclDO = Tacmach.tclDO -let tclPROGRESS = Tacmach.tclPROGRESS -let tclWEAK_PROGRESS = Tacmach.tclWEAK_PROGRESS +(*************************************************) +(* Tacticals re-exported from the Refiner module.*) +(*************************************************) + +let tclIDTAC = tclIDTAC +let tclORELSE = tclORELSE +let tclTHEN = tclTHEN +let tclTHENLIST = tclTHENLIST +let tclTHEN_i = tclTHEN_i +let tclTHENFIRST = tclTHENFIRST +let tclTHENLAST = tclTHENLAST +let tclTHENS = tclTHENS +let tclTHENSV = Refiner.tclTHENSV +let tclTHENSFIRSTn = Refiner.tclTHENSFIRSTn +let tclTHENSLASTn = Refiner.tclTHENSLASTn +let tclTHENFIRSTn = Refiner.tclTHENFIRSTn +let tclTHENLASTn = Refiner.tclTHENLASTn +let tclREPEAT = Refiner.tclREPEAT +let tclREPEAT_MAIN = tclREPEAT_MAIN +let tclFIRST = Refiner.tclFIRST +let tclSOLVE = Refiner.tclSOLVE +let tclTRY = Refiner.tclTRY +let tclINFO = Refiner.tclINFO +let tclCOMPLETE = Refiner.tclCOMPLETE +let tclAT_LEAST_ONCE = Refiner.tclAT_LEAST_ONCE +let tclFAIL = Refiner.tclFAIL +let tclDO = Refiner.tclDO +let tclPROGRESS = Refiner.tclPROGRESS +let tclWEAK_PROGRESS = Refiner.tclWEAK_PROGRESS +let tclNOTSAMEGOAL = Refiner.tclNOTSAMEGOAL +let tclTHENTRY = tclTHENTRY + +let unTAC = unTAC (* [rclTHENSEQ [t1;..;tn] is equivalent to t1;..;tn *) let tclTHENSEQ = List.fold_left tclTHEN tclIDTAC @@ -56,10 +72,6 @@ let tclTHENSEQ = List.fold_left tclTHEN tclIDTAC let tclMAP tacfun l = List.fold_right (fun x -> (tclTHEN (tacfun x))) l tclIDTAC -(*let dyn_tclIDTAC = function [] -> tclIDTAC | _ -> anomaly "tclIDTAC"*) - -(*let dyn_tclFAIL = function [] -> tclFAIL | _ -> anomaly "tclFAIL"*) - (* apply a tactic to the nth element of the signature *) let tclNTH_HYP m (tac : constr->tactic) gl = @@ -187,30 +199,6 @@ let tryAllHyps tac gls = tryClauses tac (allHyps gls) gls let onNLastHyps n tac = onHyps (nLastHyps n) (tclMAP tac) let onLastHyp tac gls = tac (lastHyp gls) gls -(* Serait-ce possible de compiler d'abord la tactique puis de faire la - substitution sans passer par bdize dont l'objectif est de préparer un - terme pour l'affichage ? (HH) *) - -(* Si on enlève le dernier argument (gl) conclPattern est calculé une -fois pour toutes : en particulier si Pattern.somatch produit une UserError -Ce qui fait que si la conclusion ne matche pas le pattern, Auto échoue, même -si après Intros la conclusion matche le pattern. -*) - -(* conclPattern doit échouer avec error car il est rattraper par tclFIRST *) - -let conclPattern concl pat tacast gl = - let constr_bindings = - try Pattern.matches pat concl - with PatternMatchingFailure -> error "conclPattern" in - let ast_bindings = - List.map - (fun (i,c) -> - (i, Termast.ast_of_constr false (pf_env gl) c)) - constr_bindings in - let tacast' = Coqast.subst_meta ast_bindings tacast in - Tacinterp.interp tacast' gl - let clauseTacThen tac continuation = (fun cls -> (tclTHEN (tac cls) continuation)) @@ -252,7 +240,7 @@ type branch_args = { type branch_assumptions = { ba : branch_args; (* the branch args *) - assums : named_context; (* the list of assumptions introduced *) + assums : named_context; (* the list of assumptions introduced *) cargs : identifier list; (* the constructor arguments *) constargs : identifier list; (* the CONSTANT constructor arguments *) recargs : identifier list; (* the RECURSIVE constructor arguments *) @@ -337,24 +325,25 @@ let general_elim_then_using let branchsigns = elim_sign_fun ity in let after_tac ce i gl = let (hd,largs) = decompose_app (clenv_template_type ce).rebus in - let ba = { branchsign = branchsigns.(i-1); + let ba = { branchsign = branchsigns.(i); nassums = List.fold_left (fun acc b -> if b then acc+2 else acc+1) - 0 branchsigns.(i-1); - branchnum = i; + 0 branchsigns.(i); + branchnum = i+1; ity = ity; largs = List.map (clenv_instance_term ce) largs; pred = clenv_instance_term ce hd } in tac ba gl in + let branchtacs ce = Array.init (Array.length branchsigns) (after_tac ce) in let elimclause' = match predicate with | None -> elimclause' | Some p -> clenv_assign pmv p elimclause' in - elim_res_pf_THEN_i kONT elimclause' after_tac gl + elim_res_pf_THEN_i kONT elimclause' branchtacs gl let elimination_then_using tac predicate (indbindings,elimbindings) c gl = diff --git a/tactics/tacticals.mli b/tactics/tacticals.mli index 90cb04f3e..0557be882 100644 --- a/tactics/tacticals.mli +++ b/tactics/tacticals.mli @@ -25,12 +25,19 @@ open Wcclausenv val tclIDTAC : tactic val tclORELSE : tactic -> tactic -> tactic val tclTHEN : tactic -> tactic -> tactic +val tclTHENSEQ : tactic list -> tactic +val tclTHENLIST : tactic list -> tactic val tclTHEN_i : tactic -> (int -> tactic) -> tactic -val tclTHENL : tactic -> tactic -> tactic +val tclTHENFIRST : tactic -> tactic -> tactic +val tclTHENLAST : tactic -> tactic -> tactic val tclTHENS : tactic -> tactic list -> tactic -val tclTHENSi : tactic -> tactic list -> (int -> tactic) -> tactic -val tclTHENSEQ : tactic list -> tactic +val tclTHENSV : tactic -> tactic array -> tactic +val tclTHENSLASTn : tactic -> tactic -> tactic array -> tactic +val tclTHENLASTn : tactic -> tactic array -> tactic +val tclTHENSFIRSTn : tactic -> tactic array -> tactic -> tactic +val tclTHENFIRSTn : tactic -> tactic array -> tactic val tclREPEAT : tactic -> tactic +val tclREPEAT_MAIN : tactic -> tactic val tclFIRST : tactic list -> tactic val tclSOLVE : tactic list -> tactic val tclTRY : tactic -> tactic @@ -41,16 +48,16 @@ val tclFAIL : int -> tactic val tclDO : int -> tactic -> tactic val tclPROGRESS : tactic -> tactic val tclWEAK_PROGRESS : tactic -> tactic +val tclNOTSAMEGOAL : tactic -> tactic +val tclTHENTRY : tactic -> tactic -> tactic + val tclNTH_HYP : int -> (constr -> tactic) -> tactic val tclMAP : ('a -> tactic) -> 'a list -> tactic val tclLAST_HYP : (constr -> tactic) -> tactic val tclTRY_sign : (constr -> tactic) -> named_context -> tactic val tclTRY_HYPS : (constr -> tactic) -> tactic -(*i -val dyn_tclIDTAC : tactic_arg list -> tactic -val dyn_tclFAIL : tactic_arg list -> tactic -i*) +val unTAC : tactic -> goal sigma -> proof_tree sigma (*s Clause tacticals. *) @@ -59,10 +66,6 @@ type clause = identifier option val nth_clause : int -> goal sigma -> clause val clause_type : clause -> goal sigma -> constr -(*i -val matches : goal sigma -> constr -> marked_term -> bool -val dest_match : goal sigma -> constr -> marked_term -> constr list -i*) val pf_matches : goal sigma -> constr_pattern -> constr -> (int * constr) list val pf_is_matching : goal sigma -> constr_pattern -> constr -> bool @@ -95,13 +98,6 @@ val tryAllHyps : (identifier -> tactic) -> tactic val onNLastHyps : int -> (named_declaration -> tactic) -> tactic val onLastHyp : (identifier -> tactic) -> tactic -(* [ConclPattern concl pat tacast]: - if the term concl matches the pattern pat, (in sense of - [Pattern.somatches], then replace [?1] [?2] metavars in tacast by the - right values to build a tactic *) - -val conclPattern : constr -> constr_pattern -> Coqast.t -> tactic - (*s Elimination tacticals. *) type branch_args = { |