p<=q -> True. +Proof. + intros n m p q H H0 H1. + Unset Silent. + map_all_hyps ltac:(fun h => idtac h). + map_all_hyps_rev ltac:(fun h => idtac h). + onAllHyps (fun h => idtac h). + onAllHypsRev (fun h => idtac h). + ltac2:(Ltac2.then_eachnh (fun () => induction H) (fun id => printf "%I" id)). + Undo 1. + then_eachnh ltac:(induction H) ltac:(fun h => idtac h). + Undo 1. + then_eachnh_rev ltac:(induction H) ltac:(fun h => idtac h). + Undo 1. + induction H ;{ fun h => idtac h }. + Undo 1. + induction H ;{< fun h => idtac h }. *) diff --git a/Makefile b/Makefile index 8b80794..a6af6cf 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,13 @@ -lib: +.PHONY: tests LibHyps + +lib: sanity + make -C LibHyps + +# Use this instead of make lib when the debug code is present +make debug: make -C LibHyps + make -C tests tests: lib make -C tests @@ -18,3 +25,5 @@ clean: install: lib make -C LibHyps install +sanity: + @./testDebug.sh diff --git a/configure.sh b/configure.sh index beabc6c..4904fe4 100755 --- a/configure.sh +++ b/configure.sh @@ -1,15 +1,51 @@ #!/bin/bash +DEVOPT=no +STDLIB= + +POSITIONAL=() +while [[ $# -gt 0 ]] +do +key="$1" + +case $key in + --stdlib|-stdlib) + shift + STDLIB=$1 + shift + ;; + --dev) + DEVOPT=yes + shift + ;; + *) # unknown option + POSITIONAL+=("$1") # save it in an array for later + shift # past argument + ;; +esac +done + +set -- "${POSITIONAL[@]}" # restore positional parameters (i.e. + # parameters that were not recognized by the + # previous code.) function gen_projet_file () { FILES="$1" DIR=$2 + STDLIB=$4 PROJECTFILE=$DIR/_CoqProject RESOURCEFILE=$3 - cat < $RESOURCEFILE > "$PROJECTFILE" + if [ "$STDLIB" != "" ] + then + echo "stdlib detected" + echo "-Q $STDLIB Stdlib" > "$PROJECTFILE" + else echo "" > "$PROJECTFILE" + fi + + cat < $RESOURCEFILE >> "$PROJECTFILE" echo "" >> "$PROJECTFILE" @@ -27,11 +63,18 @@ function gen_projet_file () { } -FILESLH=$(cd LibHyps && find . -name "*.v" | grep -v "ident_of_string\|especialize_ltac2\|LibEspecialize" ) +if [ "$DEVOPT" = "no" ] +then + FILESLH=$(cd LibHyps && find . -name "*.v" | grep -v "ident_of_string\|especialize_ltac2\|LibEspecialize\|LibHypsDebug" ) +else + FILESLH=$(cd LibHyps && find . -name "*.v" | grep -v "ident_of_string\|especialize_ltac2\|LibEspecialize" ) +fi + PROJECTDIRLH="LibHyps" -gen_projet_file "$FILESLH" "$PROJECTDIRLH" "resources/coq_project.libhyps" +gen_projet_file "$FILESLH" "$PROJECTDIRLH" "resources/coq_project.libhyps" "$STDLIB" + FILESTEST=$(cd tests && find . -name "*.v" | grep -v "incremental" ) PROJECTDIRTESTS="tests" -gen_projet_file "$FILESTEST" "$PROJECTDIRTESTS" "resources/coq_project.tests" +gen_projet_file "$FILESTEST" "$PROJECTDIRTESTS" "resources/coq_project.tests" "$STDLIB" diff --git a/testDebug.sh b/testDebug.sh new file mode 100755 index 0000000..b7cc63c --- /dev/null +++ b/testDebug.sh @@ -0,0 +1,22 @@ +#!/bin/bash + + +## Explanation +# - Debug code is in LibHyps/LibHypsDebug.v +# +# - by default ./configure.sh does ignores this file +# - unless we use ./configure.sh --dev +# +# - the present test checks that we have not forgotten to remove +# - refrences to the debug file (by doing ./configure.sh). +# +echo "Sanity check (debug files)" +if grep -q "LibHypsDebug.v" LibHyps/_CoqProject +then + echo "REMAINING DEBUG CODE: ABORTING." + echo "Use ./configure.sh to remove rerferences to debug code." + echo "then make clean; make lib tests" + exit 1 +else + exit 0 +fi diff --git a/tests/Especialize_tests.v b/tests/Especialize_tests.v index 10eef6a..4a3fa03 100644 --- a/tests/Especialize_tests.v +++ b/tests/Especialize_tests.v @@ -1,4 +1,4 @@ -Require Import LibHyps.LibHypsTactics. +(* Require Import LibHyps.LibHypsTactics. *) Require Import LibHyps.Especialize. (* tests *) diff --git a/tests/LibHypsRegression.v b/tests/LibHypsRegression.v index 284b385..c2520d6 100644 --- a/tests/LibHypsRegression.v +++ b/tests/LibHypsRegression.v @@ -8,36 +8,43 @@ Require Export LibHyps.LibHypsNaming. Require Export LibHyps.LibHyps. Export TacNewHyps.Notations. From Stdlib Require Import Arith ZArith List. +Require Import Ltac2.Ltac2. +From Ltac2 Require Import Option Constr Printf. +Local Set Default Proof Mode "Classic". +Import ListNotations. Import LibHyps.LegacyNotations. (* This settings should reproduce the naming scheme of libhypps-1.0.0 and libhypps-1.0.1. *) -Ltac add_suffix ::= constr:(false). -Ltac numerical_names ::= numerical_names_sufx. - -Local Open Scope autonaming_scope. -Import ListNotations. - -(* From there this is LibHypTest from 1f7a1ed2289e439c291fcbd06c51705547feef1e *) -Ltac rename_hyp_2 n th := - match th with - | true <> false => name(`_tNEQf`) - | true = false => name(`_tEQf`) +Ltac2 Set numerical_sufx := true. +Ltac2 Set add_suffix := false. + +Ltac2 rename_hyp_1 n th := + if Int.lt n 0 then [] + else + lazy_match! th with + | @cons _ ?x (cons ?y ?l) => [String "cons"; Rename x; Rename y; RenameN (decr (decr n)) l] + | @cons _ ?x ?l => if Int.ge n 1 then [String "cons"; Rename x; RenameN (decr n) l] else [String "cons"] + end. + +Ltac2 rename_hyp_2 n th := + match! th with + | true <> false => [ String "tNEQf" ] + | true = false => [ String "tEQf"] + | _ => rename_hyp_1 n th (* call the previously defined tactic *) end. -Ltac rename_hyp ::= rename_hyp_2. +Ltac2 Set rename_hyp := rename_hyp_2. -(* Suppose I want to add later another naming rule: *) -Ltac rename_hyp_3 n th := - match th with - | Nat.eqb ?x ?y = true => name(`_Neqb` ++ x#n ++ y#n) - | true = Nat.eqb ?x ?y => name(`_Neqb` ++ x#n ++ y#n) +Ltac2 rename_hyp_3 n th := + match! th with + | Nat.eqb ?x ?y = true => [ String "Neqb" ; Rename x ; Rename y ] + | true = Nat.eqb ?x ?y => [ String "Neqb" ; Rename x ; Rename y ] | _ => rename_hyp_2 n th (* call the previously defined tactic *) end. -Ltac rename_hyp ::= rename_hyp_3. -Ltac rename_depth ::= constr:(3). +Ltac2 Set rename_hyp := rename_hyp_3. Close Scope Z_scope. Open Scope nat_scope. @@ -49,7 +56,10 @@ Lemma dummy: forall x y, 0 = 1 -> (0 = 1)%Z -> ~x = y -> + Nat.eqb (x + 1) 0 <> Nat.eqb 1 y -> true = Nat.eqb 3 4 -> + Nat.eqb (x + 3) 4 = true -> + Nat.eqb (2 * (x + 3)) 4 = true -> Nat.eqb 3 4 = true -> true = Nat.leb 3 4 -> 1 = 0 -> @@ -90,9 +100,11 @@ Lemma dummy: forall x y, match type of h_neq_x_y with x <> y => idtac | _ => fail "test failed!" end. match type of h_Neqb_3n_4n with true = (3 =? 4) => idtac | _ => fail "test failed!" end. match type of h_Neqb_3n_4n0 with (3 =? 4) = true => idtac | _ => fail "test failed!" end. + match type of h_Neqb_mul_2n_add_4n with (2 * (x + 3) =? 4) = true => idtac | _ => fail "test failed!" end. match type of h_eq_true_leb_3n_4n with true = (3 <=? 4) => idtac | _ => fail "test failed!" end. match type of h_eq_1n_0n with 1 = 0 => idtac | _ => fail "test failed!" end. match type of h_neq_x_y0 with x <> y => idtac | _ => fail "test failed!" end. + match type of h_neq_eqb_add_0n_eqb_1n_y with (x + 1 =? 0) <> (1 =? y) => idtac | _ => fail "test failed!" end. match type of h_not_lt_1n_0n with ~ 1 < 0 => idtac | _ => fail "test failed!" end. match type of h_all_tNEQf with forall w w' : nat, w = w' -> true <> false => idtac | _ => fail "test failed!" end. match type of h_all_and_tEQf_True with forall w w' : nat, w = w' -> true = false /\ True => idtac | _ => fail "test failed!" end. @@ -101,7 +113,7 @@ Lemma dummy: forall x y, match type of h_ex_and_True_False with exists w : nat, w = w -> True /\ False => idtac | _ => fail "test failed!" end. match type of h_all_tEQf with forall w w' : nat, w = w' -> true = false => idtac | _ => fail "test failed!" end. match type of h_all_eq_eqb_eqb with forall w w' : nat, w = w' -> (3 =? 4) = (4 =? 3) => idtac | _ => fail "test failed!" end. - match type of h_eq_length_cons with length [3] = (fun _ : nat => 0) 1 => idtac | _ => fail "test failed!" end. + match type of h_eq_length_cons with (length [3] = (fun _ : nat => 0) 1) => idtac | _ => fail "test failed!" end. match type of h_eq_length_cons_0n with length [3] = 0 => idtac | _ => fail "test failed!" end. match type of h_eq_add_0n_y_y with 0 + y = y => idtac | _ => fail "test failed!" end. match type of h_tEQf with true = false => idtac | _ => fail "test failed!" end. @@ -123,36 +135,46 @@ Qed. -(* + +Definition eq_one (i:nat) := i = 1. Lemma test_espec_namings: forall n:nat, (eq_one n -> eq_one 1 -> False) -> True. Proof. intros n h_eqone. - especialize Nat.quadmul_le_squareadd with a at 1 as hh : h. + especialize Nat.quadmul_le_squareadd with a at 1 as hh (*: h*). { apply le_n. } especialize min_l with n,m at 1 as ?. { apply (le_n O). } - especialize h_eqone at 2 as h1 : h2. + especialize h_eqone at 2 as h1 (*: h2 *). { reflexivity. } - unfold eq_one in h2. - match type of h2 with 1 = 1 => idtac | _ => fail end. + (* unfold eq_one in h2. *) + (* match type of h2 with 1 = 1 => idtac | _ => fail end. *) match type of h1 with eq_one n -> False => idtac | _ => fail end. exact I. Qed. -*) + + +Ltac2 rename_hyp_4 n th := + match! th with + | length ?l => [ String "lgth" ; Rename l ] + | _ => rename_hyp_3 n th (* call the previously defined tactic *) + end. + +Ltac2 Set rename_hyp := rename_hyp_4. Require Import LibHyps.LibDecomp. +Ltac2 Set rename_depth := 3. Goal forall l1 l2 l3:list nat, List.length l1 = List.length l2 /\ List.length l1 = List.length l3 -> True. Proof. - intros l1 l2 l3 h. + intros l1 l2 l3 ?/n. (* then_allnh_gen ltac:(fun x => all_hyps) ltac:(fun _ => decomp_logicals h) ltac:(fun lh => idtac lh) . *) (* Set Ltac Debug. *) - decomp_logicals h /sng. + decomp_logicals h_and_eq_lgth_lgth_eq_lgth_lgth /sn. match goal with |- _ => - match type of h_eq_length_l1_length_l2 with + match type of h_eq_lgth_l1_lgth_l2 with length l1 = length l2 => idtac | _ => fail "Test failed (wrong type)!" end diff --git a/tests/LibHypsTest.v b/tests/LibHypsTest.v index 78c2e60..38e9d0e 100644 --- a/tests/LibHypsTest.v +++ b/tests/LibHypsTest.v @@ -4,33 +4,43 @@ From Stdlib Require Import Arith ZArith List. Require Import LibHyps.LibHyps (*LibHyps.LibSpecialize*). +Require Import Ltac2.Ltac2. From Stdlib Require Import List. -Local Open Scope autonaming_scope. Import ListNotations. -Ltac rename_hyp_2 n th := - match th with - | true <> false => name(`_tNEQf`) - | true = false => name(`_tEQf`) +Ltac2 rename_hyp_2 n th := + match! th with + | true <> false => [ String "tNEQf" ] + | true = false => [ String "tEQf" ] end. -Ltac rename_hyp ::= rename_hyp_2. +Ltac2 Set rename_hyp := rename_hyp_2. (* Suppose I want to add later another naming rule: *) -Ltac rename_hyp_3 n th := - match th with - | Nat.eqb ?x ?y = true => name(`_Neqb` ++ x#n ++ y#n) - | true = Nat.eqb ?x ?y => name(`_Neqb` ++ x#n ++ y#n) +Ltac2 rename_hyp_3 n th := + match! th with + | Nat.eqb ?x ?y = true => [ String "Neqb"; Rename x ; Rename y ] + | true = Nat.eqb ?x ?y => [ String "Neqb" ; Rename x ; Rename y ] | _ => rename_hyp_2 n th (* call the previously defined tactic *) end. -Ltac rename_hyp ::= rename_hyp_3. -Ltac rename_depth ::= constr:(3). +Ltac2 Set rename_hyp := rename_hyp_3. + +Ltac2 rename_hyp_4 n th := + lazy_match! th with + | @cons _ ?x (cons ?y ?l) => [String "cons"; Rename x; Rename y; RenameN (decr (decr n)) l] + | @cons _ ?x ?l => if Int.ge n 1 then [String "cons"; Rename x; RenameN (decr n) l] else [String "cons"] + | _ => rename_hyp_3 n th (* call the previously defined tactic *) + end. + +Ltac2 Set rename_hyp := rename_hyp_4. + +Ltac2 rename_depth := 3. -Close Scope autonaming_scope. Close Scope Z_scope. Open Scope nat_scope. +Local Set Default Proof Mode "Classic". Ltac test h th := match type of h with @@ -172,7 +182,9 @@ Lemma test_rename_or_revert: forall x y:nat, (0 < 1 -> 1<0) -> 0 < z -> True. Proof. intros ; { rename_or_revert }. - testg ((fun _ : bool => x = y) true -> True). + match goal with + | |- _ -> True => idtac + end. auto. Qed. @@ -186,7 +198,9 @@ Lemma test_rename_or_revert2: forall x y:nat, (0 < 1 -> 1<0) -> 0 < z -> True. Proof. intros /n?. - testg ((fun _ : bool => x = y) true -> True). + match goal with + | |- _ -> True => idtac + end. test x (nat). test y (nat). (* Checking that hyps after the failed rename are introduced. *) @@ -233,7 +247,7 @@ Lemma test_group_up_list2: forall x y:nat, x = y -> (0 < 1 -> 1<0) -> 0 < z -> True. Proof. - intros ; {! group_up_list }. + intros ; { move_up_types }. lazymatch reverse goal with | Hb:_, Ha:_,Hz : _ , Hy:_ , Hx:_ |- True => let t := constr:((ltac:(reflexivity)): Hb=b) in @@ -291,43 +305,6 @@ Proof. exact I. Qed. -(* group_up_list is insensitive to order of hypothesis. It respects - the respective order of variables in each segment. This has changed - in version 2.0.5 together with a bug fix. - Note that the deprecated move_up_types is sensitive to order. *) -Lemma test_group_up_list1_rev: forall x y:nat, - ((fun f => x = y) true) - -> forall a b: bool, forall z:nat, - 0 <= 1 -> - (0%Z <= 1%Z)%Z -> - x <= y -> - x = y -> - (0 < 1 -> 1<0) -> 0 < z -> True. -Proof. - intros ; {!< group_up_list }. - lazymatch reverse goal with - | Hb:_, Ha:_,Hz : _ , Hy:_ , Hx:_ |- True => - let t := constr:((ltac:(reflexivity)): Hb=b) in - let t := constr:((ltac:(reflexivity)): Ha=a) in - let t := constr:((ltac:(reflexivity)): Hz=z) in - let t := constr:((ltac:(reflexivity)): Hy=y) in - let t := constr:((ltac:(reflexivity)): Hx=x) in - idtac - | _ => fail "test failed (wrong order of hypothesis)!" - end. - lazymatch goal with - | hH1:_, hH2:_,hH3 : _ , hH4:_ , hH5:_ |- True => - let t := constr:((ltac:(reflexivity)):H1=hH1) in - let t := constr:((ltac:(reflexivity)): H2=hH2) in - let t := constr:((ltac:(reflexivity)): H3=hH3) in - let t := constr:((ltac:(reflexivity)): H4=hH4) in - let t := constr:((ltac:(reflexivity)): H5=hH5) in - idtac - | _ => fail "test failed (wrong order of hypothesis)!" - end. - exact I. - Qed. - (* Two more tests for the case where the top hyp is Prop-sorted. *) Lemma test_group_up_list3: @@ -435,7 +412,7 @@ Lemma test_group_up_after_subst: forall x y:nat, x = y -> (0 < 1 -> 1<0) -> 0 < z -> True. Proof. - intros ; { subst_or_idtac } ; {! group_up_list }. + intros ; { subst_or_idtac } ; { move_up_types }. lazymatch reverse goal with | Hb:_, Ha:_,Hz:_ , Hy:_ |- True => let t := constr:((ltac:(reflexivity)): Hb=b) in @@ -459,87 +436,6 @@ Proof. Qed. -Ltac substHyp H ::= - match type of H with - | Depl => fail 1 (* fail immediately, we are applying on a list of hyps. *) - | ?x = ?y => - (* subst would maybe subst using another hyp, so use replace to be sure *) - once ((is_var(x); replace x with y in *; [try clear x ; try clear H] ) - + (is_var(y);replace y with x in * ; [ try clear H])) - | _ => idtac - end. - - -(* Legacy Notations tac ;!; tac2. *) -Lemma test_tactical_semi: forall x y:nat, - ((fun f => x = y) true) - -> forall a b: bool, forall z:nat, - 0 <= 1 -> - (0%Z <= 1%Z)%Z -> - x <= y -> - x = y -> - (0 < 1 -> 1<0) -> 0 < z -> True. -Proof. - (* move_up_types is there for backward compatibility. It moves Type-Sorted hyps up. *) - intros ;; move_up_types. - lazymatch reverse goal with - | Hb:_, Ha:_,Hz : _ , Hy:_ , Hx:_ |- True => - let t := constr:((ltac:(reflexivity)): Hb=b) in - let t := constr:((ltac:(reflexivity)): Ha=a) in - let t := constr:((ltac:(reflexivity)): Hz=z) in - let t := constr:((ltac:(reflexivity)): Hy=y) in - let t := constr:((ltac:(reflexivity)): Hx=x) in - idtac - | _ => fail "test failed (wrong order of hypothesis)!" - end. - lazymatch goal with - | hH1:_, hH2:_,hH3 : _ , hH4:_ , hH5:_ |- True => - let t := constr:((ltac:(reflexivity)): H1=hH1) in - let t := constr:((ltac:(reflexivity)): H2=hH2) in - let t := constr:((ltac:(reflexivity)): H3=hH3) in - let t := constr:((ltac:(reflexivity)): H4=hH4) in - let t := constr:((ltac:(reflexivity)): H5=hH5) in - idtac - | _ => fail "test failed (wrong order of hypothesis)!" - end. - auto. -Qed. - -(* Legacy Notations tac ;; tac2. *) -Lemma test_tactical_semi_rev: forall x y:nat, - ((fun f => x = y) true) - -> forall a b: bool, forall z u:nat, - 0 <= 1 -> - (0%Z <= 1%Z)%Z -> - x <= y -> - x = y -> - (0 < 1 -> 1<0) -> 0 < z -> True. -Proof. - (* move_up_types is there for backward compatibility. It moves Type-Sorted hyps up. *) - intros ;!; move_up_types. - lazymatch reverse goal with - | Ha:_, Hb:_, Hz: _ , Hu : _ , Hy:_ , Hx:_ |- True => - let t := constr:((ltac:(reflexivity)): Hb=b) in - let t := constr:((ltac:(reflexivity)): Ha=a) in - let t := constr:((ltac:(reflexivity)): Hu=u) in - let t := constr:((ltac:(reflexivity)): Hz=z) in - let t := constr:((ltac:(reflexivity)): Hy=y) in - let t := constr:((ltac:(reflexivity)): Hx=x) in - idtac - | _ => fail "test failed (wrong order of hypothesis)!" - end. - lazymatch goal with - | hH1:_, hH2:_,hH3 : _ , hH4:_ , hH5:_ |- True => - let t := constr:((ltac:(reflexivity)): H1=hH1) in - let t := constr:((ltac:(reflexivity)): H2=hH2) in - let t := constr:((ltac:(reflexivity)): H3=hH3) in - let t := constr:((ltac:(reflexivity)): H4=hH4) in - let t := constr:((ltac:(reflexivity)): H5=hH5) in - idtac - | _ => fail "test failed (wrong order of hypothesis)!" - end. - auto. -Qed. (* Legacy Notations !!!!tac. *) @@ -641,7 +537,7 @@ Lemma foo': (a b:bool), True -> forall y z:nat, True. (* Time intros. (* .07s *) *) (* Time intros; { fun x => idtac x}. (* 1,6s *) *) - Time intros /g. (* 3s *) + Time intros /g. (* Ltac with cache: 3s, Ltac2: 0,04s *) (* Time intros ; { move_up_types }. (* ~7mn *) *) (* Time intros /n. (* 19s *) *) exact I. diff --git a/tests/demo.v b/tests/demo.v index 7c24db4..67b20da 100644 --- a/tests/demo.v +++ b/tests/demo.v @@ -20,7 +20,7 @@ From Stdlib Require Import Arith ZArith List. Require Import LibHyps.LibHyps. Lemma demo: forall x y z:nat, - x = y -> forall a b t : nat, a+1 = t+2 -> b + 5 = t - 7 -> (forall u v, v+1 = 1 -> u+1 = 1 -> a+1 = z+2) -> z = b + x-> True. + x = y -> x+y = y+ z -> forall a b t : nat, a+1 = t+2 -> b + 5 = t - 7 -> (forall u v, v+1 = 1 -> u+1 = 1 -> a+1 = z+2) -> z = b + x-> True. Proof. intros. (* ugly names *) @@ -203,10 +203,7 @@ Proof. (* Better do that on new hyps only. *) intros ; { move_up_types }. Undo. - (* Faster version dealing with the whole list of new hyps at once: *) - intros; {! group_up_list }. - Undo. - (* Shortcut for this faster version: *) + (* Shortcut: *) intros /g. Undo. (* combined with subst: *) @@ -270,59 +267,42 @@ Abort. (* customization of autorename *) -Local Open Scope autonaming_scope. +(* Local Open Scope autonaming_scope. *) Import ListNotations. - +Require Import Ltac2.Ltac2. (* Define the naming scheme as new tactic pattern matching on a type th, and the depth n of the recursive naming analysis. Here we state that a type starting with Nat.eqb should start with _Neqb, followed by the name of both arguments. #n here means normal decrement of depth. (S n) would increase depth by 1 (n-1) would decrease depth. *) -Ltac rename_hyp_2 n th := - match th with - | Nat.eqb ?x ?y => name(`_Neqb` ++ x#n ++ y#n) + +Ltac2 rename_hyp_2 _n th := + match! th with + | Nat.eqb ?x ?y => [ String "Neqb" ; Rename x ; Rename y] end. (* Then overwrite the customization hook of the naming tactic *) -Ltac rename_hyp ::= rename_hyp_2. - -Goal forall x y:nat, True. - intros. - (* computing a few names *) - (* Customize the starting depth *) +Ltac2 Set rename_hyp := rename_hyp_2. - let res := fallback_rename_hyp_name (Nat.eqb 1 2) in idtac res. - let res := fallback_rename_hyp_name (Nat.eqb x 4) in idtac res. - let res := fallback_rename_hyp_name (Nat.eqb 1 2 = false) in idtac res. - Ltac rename_depth ::= constr:(2). - let res := fallback_rename_hyp_name (Nat.eqb 1 2 = false) in idtac res. - Ltac rename_depth ::= constr:(3). -Abort. (** Suppose I want to add another naming rule: I need to cumulate the previous scheme with the new one. First define a new tactic that will replace the old one. it should call previous naming schemes in case of failure of the new scheme. It is thus important that rename_hyp_2 was defined by itself and directly as rename_hyp. *) -Ltac rename_hyp_3 n th := - match th with - | ?x = false => name(x#n ++ `_isf`) - | ?x = true => name( x#n ++ `_ist`) +Ltac2 rename_hyp_3 n th := + match! th with + | ?x = false => [ Rename x ; String "isf" ] + | ?x = true => [ Rename x ; String "ist" ] | _ => rename_hyp_2 n th (* previous naming scheme *) end. (* Then update the customization hook *) -Ltac rename_hyp ::= rename_hyp_3. +Ltac2 Set rename_hyp := rename_hyp_3. (* Close the naming scope *) -Local Close Scope autonaming_scope. - -Goal forall x y:nat, True. - intros. - let res := fallback_rename_hyp_name (Nat.eqb 1 2 = false) in - idtac res. -Abort. +Local Set Default Proof Mode "Classic". Lemma foo: forall (x:nat) (b1:bool) (y:nat) (b2:bool), x = y @@ -336,12 +316,12 @@ Lemma foo: forall (x:nat) (b1:bool) (y:nat) (b2:bool), -> z = b + 5-> z' + 1 = b + x-> x < y + b. Proof. (* Customize the starting depth *) - Ltac rename_depth ::= constr:(3). + Ltac2 Set rename_depth := 3. intros/n/g. Undo. (* Have shorter names: *) - Ltac rename_depth ::= constr:(2). + Ltac2 Set rename_depth := 2. intros/n/g.