From c8f818c7fd711a54d5bf17e3ecd24f66725d01d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment?= <clef-men@orange.fr> Date: Sun, 24 Nov 2024 15:38:05 +0100 Subject: [PATCH] Add custom intro patterns. --- iris/proofmode/intro_patterns.v | 12 ++++- iris/proofmode/ltac_tactics.v | 88 +++++++++++++++++++++------------ iris/proofmode/tokens.v | 4 +- 3 files changed, 70 insertions(+), 34 deletions(-) diff --git a/iris/proofmode/intro_patterns.v b/iris/proofmode/intro_patterns.v index 4e734ec3c..ba7e19a84 100644 --- a/iris/proofmode/intro_patterns.v +++ b/iris/proofmode/intro_patterns.v @@ -1,4 +1,5 @@ From stdpp Require Export strings. +From stdpp Require Import pretty. From iris.proofmode Require Import base tokens sel_patterns. From iris.prelude Require Import options. @@ -24,7 +25,8 @@ Inductive intro_pat := | IForall : intro_pat | IAll : intro_pat | IClear : sel_pat → intro_pat - | IClearFrame : sel_pat → intro_pat. + | IClearFrame : sel_pat → intro_pat + | ICustom : string → list string → intro_pat. Module intro_pat. Inductive stack_item := @@ -85,6 +87,7 @@ Fixpoint parse_go (ts : list token) (k : stack) : option stack := | TBracketL :: ts => parse_go ts (StList :: k) | TBar :: ts => parse_go ts (StBar :: k) | TBracketR :: ts => close_list k [] [] ≫= parse_go ts + | TParenL :: TColon :: TName custom :: ts => parse_custom custom [] ts k | TParenL :: ts => parse_go ts (StConjList :: k) | TAmp :: ts => parse_go ts (StAmp :: k) | TParenR :: ts => close_conj_list k None [] ≫= parse_go ts @@ -115,6 +118,13 @@ with parse_clear (ts : list token) (k : stack) : option stack := | TSep :: ts => parse_clear ts (StPat (IClear SelSpatial) :: k) | TBraceR :: ts => parse_go ts k | _ => None + end +with parse_custom custom args ts k := + match ts with + | TName arg :: ts => parse_custom custom (arg :: args) ts k + | TNat i :: ts => parse_custom custom (pretty i :: args) ts k + | TParenR :: ts => parse_go ts (StPat (ICustom custom (rev args)) :: k) + | _ => None end. Fixpoint close (k : stack) (ps : list intro_pat) : option (list intro_pat) := diff --git a/iris/proofmode/ltac_tactics.v b/iris/proofmode/ltac_tactics.v index 1018168a7..0352452f0 100644 --- a/iris/proofmode/ltac_tactics.v +++ b/iris/proofmode/ltac_tactics.v @@ -7,6 +7,11 @@ From iris.proofmode Require Export classes notation. From iris.prelude Require Import options. Export ident. +Class CustomIpat (custom : string) := + custom_ipat : list string → option string. +#[global] Arguments custom_ipat custom {CustomIpat} args : rename. +#[global] Hint Mode CustomIpat + : typeclass_instances. + (** Tactic used for solving side-conditions arising from TC resolution in [iMod] and [iInv]. *) Ltac iSolveSideCondition := @@ -298,7 +303,7 @@ Tactic Notation "iAssumption" := |exact Hass |pm_reduce; tc_solve || fail 2 "iAssumption: remaining hypotheses not affine and the goal not absorbing"] - |assert_fails (is_evar P); + |assert_fails (is_evar P); assert (P = False%I) as Hass by reflexivity; apply (tac_false_destruct _ j p P); [pm_reflexivity @@ -1570,38 +1575,57 @@ Tactic Notation "iCombine" constr(H1) constr(H2) "as" constr(pat1) (** * Introduction tactic *) Ltac _iIntros_go pats startproof := - lazymatch pats with - | [] => - lazymatch startproof with - | true => iStartProof - | false => idtac + let rec go pats startproof := + lazymatch pats with + | [] => + lazymatch startproof with + | true => iStartProof + | false => idtac + end + (* Optimizations to avoid generating fresh names *) + | IPure (IGallinaNamed ?s) :: ?pats => + let i := fresh in + iIntro (i); + rename_by_string i s; + _iIntros_go pats startproof + | IPure IGallinaAnon :: ?pats => iIntro (?); _iIntros_go pats startproof + | IIntuitionistic (IIdent ?H) :: ?pats => iIntro #H; _iIntros_go pats false + | IDrop :: ?pats => iIntro _; _iIntros_go pats startproof + | IIdent ?H :: ?pats => iIntro H; _iIntros_go pats startproof + (* Introduction patterns that can only occur at the top-level *) + | IPureIntro :: ?pats => iPureIntro; _iIntros_go pats false + | IModalIntro :: ?pats => iModIntro; _iIntros_go pats false + | IForall :: ?pats => repeat iIntroForall; _iIntros_go pats startproof + | IAll :: ?pats => repeat (iIntroForall || iIntro); _iIntros_go pats startproof + (* Clearing and simplifying introduction patterns *) + | ISimpl :: ?pats => simpl; _iIntros_go pats startproof + | IClear ?H :: ?pats => iClear H; _iIntros_go pats false + | IClearFrame ?H :: ?pats => iFrame H; _iIntros_go pats false + | IDone :: ?pats => try done; _iIntros_go pats startproof + (* Introduction + destruct *) + | IIntuitionistic ?pat :: ?pats => + let H := iFresh in iIntro #H; iDestructHyp H as pat; _iIntros_go pats false + | ICustom ?custom ?args :: ?pats => + first + [ lazymatch eval cbv in (custom_ipat custom args) with + | None => + fail 1 "iIntros: invalid arguments for custom intro pattern:" custom + | Some ?pat => + lazymatch eval cbv in (intro_pat.parse pat) with + | None => + fail 1 "iIntros: invalid intro pattern generated by custom intro pattern:" custom + | Some ?pats' => + let pats := eval cbv in (pats' ++ pats) in + go pats startproof + end + end + | fail 1 "iIntros: unrecognized custom intro pattern:" custom + ] + | ?pat :: ?pats => + let H := iFresh in iIntro H; iDestructHyp H as pat; _iIntros_go pats false end - (* Optimizations to avoid generating fresh names *) - | IPure (IGallinaNamed ?s) :: ?pats => - let i := fresh in - iIntro (i); - rename_by_string i s; - _iIntros_go pats startproof - | IPure IGallinaAnon :: ?pats => iIntro (?); _iIntros_go pats startproof - | IIntuitionistic (IIdent ?H) :: ?pats => iIntro #H; _iIntros_go pats false - | IDrop :: ?pats => iIntro _; _iIntros_go pats startproof - | IIdent ?H :: ?pats => iIntro H; _iIntros_go pats startproof - (* Introduction patterns that can only occur at the top-level *) - | IPureIntro :: ?pats => iPureIntro; _iIntros_go pats false - | IModalIntro :: ?pats => iModIntro; _iIntros_go pats false - | IForall :: ?pats => repeat iIntroForall; _iIntros_go pats startproof - | IAll :: ?pats => repeat (iIntroForall || iIntro); _iIntros_go pats startproof - (* Clearing and simplifying introduction patterns *) - | ISimpl :: ?pats => simpl; _iIntros_go pats startproof - | IClear ?H :: ?pats => iClear H; _iIntros_go pats false - | IClearFrame ?H :: ?pats => iFrame H; _iIntros_go pats false - | IDone :: ?pats => try done; _iIntros_go pats startproof - (* Introduction + destruct *) - | IIntuitionistic ?pat :: ?pats => - let H := iFresh in iIntro #H; iDestructHyp H as pat; _iIntros_go pats false - | ?pat :: ?pats => - let H := iFresh in iIntro H; iDestructHyp H as pat; _iIntros_go pats false - end. + in + go pats startproof. Ltac _iIntros0 pat := let pats := intro_pat.parse pat in diff --git a/iris/proofmode/tokens.v b/iris/proofmode/tokens.v index 8885c26d9..e761bcb80 100644 --- a/iris/proofmode/tokens.v +++ b/iris/proofmode/tokens.v @@ -26,7 +26,8 @@ Inductive token := | TAll : token | TMinus : token | TSep : token - | TArrow : direction → token. + | TArrow : direction → token + | TColon : token. Inductive state := | SName : string → state @@ -70,6 +71,7 @@ Fixpoint tokenize_go (s : string) (k : list token) (kn : state) : list token := | String "-" (String ">" s) => tokenize_go s (TArrow Right :: cons_state kn k) SNone | String "<" (String "-" s) => tokenize_go s (TArrow Left :: cons_state kn k) SNone | String "-" s => tokenize_go s (TMinus :: cons_state kn k) SNone + | String ":" s => tokenize_go s (TColon :: cons_state kn k) SNone | String (Ascii.Ascii false true false false false true true true) (* unicode ∗ *) (String (Ascii.Ascii false false false true false false false true) (String (Ascii.Ascii true true true false true false false true) s)) => -- GitLab