diff options
| -rw-r--r-- | parsing/g_tactic.ml4 | 32 | ||||
| -rw-r--r-- | parsing/pptactic.ml | 8 | ||||
| -rw-r--r-- | parsing/q_coqast.ml4 | 6 | ||||
| -rw-r--r-- | plugins/interface/depends.ml | 2 | ||||
| -rw-r--r-- | plugins/interface/xlate.ml | 4 | ||||
| -rw-r--r-- | proofs/tacexpr.ml | 12 | ||||
| -rw-r--r-- | tactics/hiddentac.ml | 12 | ||||
| -rw-r--r-- | tactics/hiddentac.mli | 4 | ||||
| -rw-r--r-- | tactics/tacinterp.ml | 22 | ||||
| -rw-r--r-- | tactics/tactics.ml | 10 | ||||
| -rw-r--r-- | tactics/tactics.mli | 8 | ||||
| -rw-r--r-- | test-suite/success/induct.v | 8 |
12 files changed, 72 insertions, 56 deletions
diff --git a/parsing/g_tactic.ml4 b/parsing/g_tactic.ml4 index 81374e2f25..68e437cab1 100644 --- a/parsing/g_tactic.ml4 +++ b/parsing/g_tactic.ml4 @@ -148,9 +148,9 @@ let induction_arg_of_constr (c,lbind as clbind) = else ElimOnConstr clbind let mkTacCase with_evar = function - | [([ElimOnConstr cl],None,(None,None),None)] -> + | [([ElimOnConstr cl],None,(None,None))],None -> TacCase (with_evar,cl) - | [([ElimOnIdent id],None,(None,None),None)] -> + | [([ElimOnIdent id],None,(None,None))],None -> TacCase (with_evar,(CRef (Ident id),NoBindings)) | ic -> TacInductionDestruct (false,with_evar,ic) @@ -462,7 +462,13 @@ GEXTEND Gram ; induction_clause: [ [ lc = LIST1 induction_arg; ipats = with_induction_names; - el = OPT eliminator; cl = opt_clause -> (lc,el,ipats,cl) ] ] + el = OPT eliminator -> (lc,el,ipats) ] ] + ; + one_induction_clause: + [ [ ic = induction_clause; cl = opt_clause -> ([ic],cl) ] ] + ; + induction_clause_list: + [ [ ic = LIST1 induction_clause SEP ","; cl = opt_clause -> (ic,cl) ] ] ; move_location: [ [ IDENT "after"; id = id_or_meta -> MoveAfter id @@ -500,8 +506,8 @@ GEXTEND Gram | IDENT "eelim"; cl = constr_with_bindings; el = OPT eliminator -> TacElim (true,cl,el) | IDENT "elimtype"; c = constr -> TacElimType c - | IDENT "case"; ic = LIST1 induction_clause SEP "," -> mkTacCase false ic - | IDENT "ecase"; ic = LIST1 induction_clause SEP "," -> mkTacCase true ic + | IDENT "case"; icl = induction_clause_list -> mkTacCase false icl + | IDENT "ecase"; icl = induction_clause_list -> mkTacCase true icl | IDENT "casetype"; c = constr -> TacCaseType c | "fix"; n = natural -> TacFix (None,n) | "fix"; id = ident; n = natural -> TacFix (Some id,n) @@ -556,18 +562,18 @@ GEXTEND Gram (* Derived basic tactics *) | IDENT "simple"; IDENT"induction"; h = quantified_hypothesis -> TacSimpleInductionDestruct (true,h) - | IDENT "induction"; ic = induction_clause -> - TacInductionDestruct (true,false,[ic]) - | IDENT "einduction"; ic = induction_clause -> - TacInductionDestruct(true,true,[ic]) + | IDENT "induction"; ic = one_induction_clause -> + TacInductionDestruct (true,false,ic) + | IDENT "einduction"; ic = one_induction_clause -> + TacInductionDestruct(true,true,ic) | IDENT "double"; IDENT "induction"; h1 = quantified_hypothesis; h2 = quantified_hypothesis -> TacDoubleInduction (h1,h2) | IDENT "simple"; IDENT "destruct"; h = quantified_hypothesis -> TacSimpleInductionDestruct (false,h) - | IDENT "destruct"; ic = LIST1 induction_clause SEP "," -> - TacInductionDestruct(false,false,ic) - | IDENT "edestruct"; ic = LIST1 induction_clause SEP "," -> - TacInductionDestruct(false,true,ic) + | IDENT "destruct"; icl = induction_clause_list -> + TacInductionDestruct(false,false,icl) + | IDENT "edestruct"; icl = induction_clause_list -> + TacInductionDestruct(false,true,icl) | IDENT "decompose"; IDENT "record" ; c = constr -> TacDecomposeAnd c | IDENT "decompose"; IDENT "sum"; c = constr -> TacDecomposeOr c | IDENT "decompose"; "["; l = LIST1 smart_global; "]"; c = constr diff --git a/parsing/pptactic.ml b/parsing/pptactic.ml index f113908f89..d316a8b05f 100644 --- a/parsing/pptactic.ml +++ b/parsing/pptactic.ml @@ -752,14 +752,14 @@ and pr_atom1 = function | TacSimpleInductionDestruct (isrec,h) -> hov 1 (str "simple " ++ str (if isrec then "induction" else "destruct") ++ pr_arg pr_quantified_hypothesis h) - | TacInductionDestruct (isrec,ev,l) -> + | TacInductionDestruct (isrec,ev,(l,cl)) -> hov 1 (str (with_evars ev (if isrec then "induction" else "destruct")) ++ spc () ++ - prlist_with_sep pr_coma (fun (h,e,ids,cl) -> + prlist_with_sep pr_coma (fun (h,e,ids) -> prlist_with_sep spc (pr_induction_arg pr_lconstr pr_constr) h ++ pr_with_induction_names ids ++ - pr_opt pr_eliminator e ++ - pr_opt_no_spc (pr_clauses pr_ident) cl) l) + pr_opt pr_eliminator e) l ++ + pr_opt_no_spc (pr_clauses pr_ident) cl) | TacDoubleInduction (h1,h2) -> hov 1 (str "double induction" ++ diff --git a/parsing/q_coqast.ml4 b/parsing/q_coqast.ml4 index cd3e7d2a83..83c4a2fdc6 100644 --- a/parsing/q_coqast.ml4 +++ b/parsing/q_coqast.ml4 @@ -367,13 +367,13 @@ let rec mlexpr_of_atomic_tactic = function $mlexpr_of_quantified_hypothesis h$ >> | Tacexpr.TacInductionDestruct (isrec,ev,l) -> <:expr< Tacexpr.TacInductionDestruct $mlexpr_of_bool isrec$ $mlexpr_of_bool ev$ - $mlexpr_of_list (mlexpr_of_quadruple + $mlexpr_of_pair (mlexpr_of_list (mlexpr_of_triple (mlexpr_of_list mlexpr_of_induction_arg) (mlexpr_of_option mlexpr_of_constr_with_binding) (mlexpr_of_pair (mlexpr_of_option (mlexpr_of_located mlexpr_of_intro_pattern)) - (mlexpr_of_option (mlexpr_of_located mlexpr_of_intro_pattern))) - (mlexpr_of_option mlexpr_of_clause)) l$ >> + (mlexpr_of_option (mlexpr_of_located mlexpr_of_intro_pattern))))) + (mlexpr_of_option mlexpr_of_clause) l$ >> (* Context management *) | Tacexpr.TacClear (b,l) -> diff --git a/plugins/interface/depends.ml b/plugins/interface/depends.ml index 1a5bfaf33d..a8bad4c66b 100644 --- a/plugins/interface/depends.ml +++ b/plugins/interface/depends.ml @@ -305,7 +305,7 @@ let rec depends_of_gen_tactic_expr depends_of_'constr depends_of_'ind depends_of (* Derived basic tactics *) | TacSimpleInductionDestruct _ | TacDoubleInduction _ -> acc - | TacInductionDestruct (_, _, [cwbial, cwbo, _, _]) -> + | TacInductionDestruct (_, _, ([cwbial, cwbo, _], _)) -> list_union_map (depends_of_'a_induction_arg depends_of_'constr_with_bindings) cwbial (Option.fold_right depends_of_'constr_with_bindings cwbo acc) diff --git a/plugins/interface/xlate.ml b/plugins/interface/xlate.ml index a322c7a72b..613c31db71 100644 --- a/plugins/interface/xlate.ml +++ b/plugins/interface/xlate.ml @@ -1229,11 +1229,11 @@ and xlate_tac = CT_dauto(xlate_int_or_var_opt_to_int_opt a, xlate_int_opt b) | TacDAuto (a, b, _) -> xlate_error "TODO: dauto using" - | TacInductionDestruct(true,false,[a,b,(None,c),None]) -> + | TacInductionDestruct(true,false,([a,b,(None,c)],None)) -> CT_new_destruct (List.map xlate_int_or_constr a, xlate_using b, xlate_with_names c) - | TacInductionDestruct(false,false,[a,b,(None,c),None]) -> + | TacInductionDestruct(false,false,([a,b,(None,c)],None)) -> CT_new_induction (List.map xlate_int_or_constr a, xlate_using b, xlate_with_names c) diff --git a/proofs/tacexpr.ml b/proofs/tacexpr.ml index ba3c27e635..c3e12c0dea 100644 --- a/proofs/tacexpr.ml +++ b/proofs/tacexpr.ml @@ -115,10 +115,12 @@ let goal_location_of = function | _ -> error "Not a simple \"in\" clause (one hypothesis or the conclusion)" -type ('constr,'id) induction_clause = - ('constr with_bindings induction_arg list * 'constr with_bindings option * - (intro_pattern_expr located option * intro_pattern_expr located option) * - 'id gclause option) +type 'constr induction_clause = + ('constr with_bindings induction_arg list * 'constr with_bindings option * + (intro_pattern_expr located option * intro_pattern_expr located option)) + +type ('constr,'id) induction_clause_list = + 'constr induction_clause list * 'id gclause option type multi = | Precisely of int @@ -170,7 +172,7 @@ type ('constr,'pat,'cst,'ind,'ref,'id,'tac) gen_atomic_tactic_expr = (* Derived basic tactics *) | TacSimpleInductionDestruct of rec_flag * quantified_hypothesis - | TacInductionDestruct of rec_flag * evars_flag * ('constr,'id) induction_clause list + | TacInductionDestruct of rec_flag * evars_flag * ('constr,'id) induction_clause_list | TacDoubleInduction of quantified_hypothesis * quantified_hypothesis | TacDecomposeAnd of 'constr | TacDecomposeOr of 'constr diff --git a/tactics/hiddentac.ml b/tactics/hiddentac.ml index 73aeec501d..d642a38dbc 100644 --- a/tactics/hiddentac.ml +++ b/tactics/hiddentac.ml @@ -83,12 +83,12 @@ let h_simple_induction_destruct isrec h = let h_simple_induction = h_simple_induction_destruct true let h_simple_destruct = h_simple_induction_destruct false -let h_induction_destruct isrec ev l = - abstract_tactic (TacInductionDestruct (isrec,ev,List.map (fun (c,e,idl,cl) -> - List.map inj_ia c,Option.map inj_open_wb e,idl,cl) l)) - (induction_destruct ev isrec l) -let h_new_induction ev c e idl cl = h_induction_destruct ev true [c,e,idl,cl] -let h_new_destruct ev c e idl cl = h_induction_destruct ev false [c,e,idl,cl] +let h_induction_destruct isrec ev (l,cl) = + abstract_tactic (TacInductionDestruct (isrec,ev,(List.map (fun (c,e,idl) -> + List.map inj_ia c,Option.map inj_open_wb e,idl) l,cl))) + (induction_destruct ev isrec (l,cl)) +let h_new_induction ev c e idl cl = h_induction_destruct ev true ([c,e,idl],cl) +let h_new_destruct ev c e idl cl = h_induction_destruct ev false ([c,e,idl],cl) let h_specialize n d = abstract_tactic (TacSpecialize (n,inj_open_wb d)) (specialize n d) let h_lapply c = abstract_tactic (TacLApply (inj_open c)) (cut_and_apply c) diff --git a/tactics/hiddentac.mli b/tactics/hiddentac.mli index f4da57144b..86a3376785 100644 --- a/tactics/hiddentac.mli +++ b/tactics/hiddentac.mli @@ -78,8 +78,8 @@ val h_new_destruct : evars_flag -> Tacticals.clause option -> tactic val h_induction_destruct : rec_flag -> evars_flag -> (constr with_ebindings induction_arg list * constr with_ebindings option * - (intro_pattern_expr located option * intro_pattern_expr located option) * - Tacticals.clause option) list -> tactic + (intro_pattern_expr located option * intro_pattern_expr located option)) list + * Tacticals.clause option -> tactic val h_specialize : int option -> constr with_ebindings -> tactic val h_lapply : constr -> tactic diff --git a/tactics/tacinterp.ml b/tactics/tacinterp.ml index 8d8b94c6cb..427a6eaa67 100644 --- a/tactics/tacinterp.ml +++ b/tactics/tacinterp.ml @@ -736,13 +736,13 @@ let rec intern_atomic lf ist x = (* Derived basic tactics *) | TacSimpleInductionDestruct (isrec,h) -> TacSimpleInductionDestruct (isrec,intern_quantified_hypothesis ist h) - | TacInductionDestruct (ev,isrec,l) -> - TacInductionDestruct (ev,isrec,List.map (fun (lc,cbo,(ipato,ipats),cls) -> + | TacInductionDestruct (ev,isrec,(l,cls)) -> + TacInductionDestruct (ev,isrec,(List.map (fun (lc,cbo,(ipato,ipats)) -> (List.map (intern_induction_arg ist) lc, Option.map (intern_constr_with_bindings ist) cbo, (Option.map (intern_intro_pattern lf ist) ipato, - Option.map (intern_intro_pattern lf ist) ipats), - Option.map (clause_app (intern_hyp_location ist)) cls)) l) + Option.map (intern_intro_pattern lf ist) ipats))) l, + Option.map (clause_app (intern_hyp_location ist)) cls)) | TacDoubleInduction (h1,h2) -> let h1 = intern_quantified_hypothesis ist h1 in let h2 = intern_quantified_hypothesis ist h2 in @@ -2281,14 +2281,14 @@ and interp_atomic ist gl = function (* Derived basic tactics *) | TacSimpleInductionDestruct (isrec,h) -> h_simple_induction_destruct isrec (interp_quantified_hypothesis ist h) - | TacInductionDestruct (isrec,ev,l) -> + | TacInductionDestruct (isrec,ev,(l,cls)) -> h_induction_destruct ev isrec - (List.map (fun (lc,cbo,(ipato,ipats),cls) -> + (List.map (fun (lc,cbo,(ipato,ipats)) -> (List.map (interp_induction_arg ist gl) lc, Option.map (interp_constr_with_bindings ist gl) cbo, (Option.map (interp_intro_pattern ist gl) ipato, - Option.map (interp_intro_pattern ist gl) ipats), - Option.map (interp_clause ist gl) cls)) l) + Option.map (interp_intro_pattern ist gl) ipats))) l, + Option.map (interp_clause ist gl) cls) | TacDoubleInduction (h1,h2) -> let h1 = interp_quantified_hypothesis ist h1 in let h2 = interp_quantified_hypothesis ist h2 in @@ -2617,10 +2617,10 @@ let rec subst_atomic subst (t:glob_atomic_tactic_expr) = match t with (* Derived basic tactics *) | TacSimpleInductionDestruct (isrec,h) as x -> x - | TacInductionDestruct (isrec,ev,l) -> - TacInductionDestruct (isrec,ev,List.map (fun (lc,cbo,ids,cls) -> + | TacInductionDestruct (isrec,ev,(l,cls)) -> + TacInductionDestruct (isrec,ev,(List.map (fun (lc,cbo,ids) -> List.map (subst_induction_arg subst) lc, - Option.map (subst_raw_with_bindings subst) cbo, ids, cls) l) + Option.map (subst_raw_with_bindings subst) cbo, ids) l, cls)) | TacDoubleInduction (h1,h2) as x -> x | TacDecomposeAnd c -> TacDecomposeAnd (subst_rawconstr subst c) | TacDecomposeOr c -> TacDecomposeOr (subst_rawconstr subst c) diff --git a/tactics/tactics.ml b/tactics/tactics.ml index 8e920ef64a..35f3b40d49 100644 --- a/tactics/tactics.ml +++ b/tactics/tactics.ml @@ -2919,12 +2919,12 @@ let induct_destruct isrec with_evars (lc,elim,names,cls) = else induct_destruct_l isrec with_evars lc elim names cls let induction_destruct isrec with_evars = function - | [] -> tclIDTAC - | [a] -> induct_destruct isrec with_evars a - | a::l -> + | [],_ -> tclIDTAC + | [a,b,c],cl -> induct_destruct isrec with_evars (a,b,c,cl) + | (a,b,c)::l,cl -> tclTHEN - (induct_destruct isrec with_evars a) - (tclMAP (induct_destruct false with_evars) l) + (induct_destruct isrec with_evars (a,b,c,cl)) + (tclMAP (fun (a,b,c) -> induct_destruct false with_evars (a,b,c,cl)) l) let new_induct ev lc e idl cls = induct_destruct true ev (lc,e,idl,cls) let new_destruct ev lc e idl cls = induct_destruct false ev (lc,e,idl,cls) diff --git a/tactics/tactics.mli b/tactics/tactics.mli index 40ff0b688e..cedcbf7caa 100644 --- a/tactics/tactics.mli +++ b/tactics/tactics.mli @@ -289,12 +289,12 @@ val new_destruct : evars_flag -> constr with_ebindings induction_arg list -> (*s Generic case analysis / induction tactics. *) -val induction_destruct : evars_flag -> rec_flag -> +val induction_destruct : rec_flag -> evars_flag -> (constr with_ebindings induction_arg list * constr with_ebindings option * - (intro_pattern_expr located option * intro_pattern_expr located option) * - clause option) list -> - tactic + (intro_pattern_expr located option * intro_pattern_expr located option)) + list * + clause option -> tactic (*s Eliminations giving the type instead of the proof. *) diff --git a/test-suite/success/induct.v b/test-suite/success/induct.v index b78651c916..aae55ec7a3 100644 --- a/test-suite/success/induct.v +++ b/test-suite/success/induct.v @@ -32,3 +32,11 @@ Check Inductive eq2 (A:Type) (a:A) : forall B C:Type, let D:=(A*B*C)%type in D -> Prop := refl2 : eq2 A a unit bool (a,tt,true). + +(* Check that induction variables are cleared even with in clause *) + +Lemma foo : forall n m : nat, n + m = n + m. +Proof. + intros; induction m as [|m] in n |- *. + auto. +Qed. |
