Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
124 commits
Select commit Hold shift + click to select a range
a735c02
basic iapply setup
oliversoeser Jul 8, 2025
cc90064
basic iapply case distinction
oliversoeser Jul 8, 2025
d940602
iapply structure
oliversoeser Jul 8, 2025
8583f03
comment out sorrys
oliversoeser Jul 9, 2025
4f0b356
comment out failing tests
oliversoeser Jul 9, 2025
6725231
iapply simple wand (n=1 case)
oliversoeser Jul 9, 2025
a100c8a
iApplyCore
oliversoeser Jul 9, 2025
72a67ba
move hypothesis removal
oliversoeser Jul 10, 2025
c4870cd
recursion
oliversoeser Jul 10, 2025
1430f9f
identify hypotheses
oliversoeser Jul 11, 2025
70c81cb
Revert
oliversoeser Jul 14, 2025
f293704
basic spec patterns
oliversoeser Jul 14, 2025
33591dc
induction step apply theorem
oliversoeser Jul 14, 2025
3e7cab4
apply' forward direction only
oliversoeser Jul 14, 2025
3b0f2d6
apply' type classes
oliversoeser Jul 14, 2025
abceb0e
proof refactor
oliversoeser Jul 15, 2025
795b55d
simple spec patterns success
oliversoeser Jul 15, 2025
d10ff64
specpat constructor
oliversoeser Jul 15, 2025
39d76ce
complex spec pat progress
oliversoeser Jul 16, 2025
d9ffddb
recursive hypothesis removal
oliversoeser Jul 17, 2025
62453b4
hypothesis removal outputs
oliversoeser Jul 17, 2025
c37a1fc
restructure
oliversoeser Jul 18, 2025
f7178bf
make apply reflect tac_apply
oliversoeser Jul 18, 2025
5e78fff
hyps split
oliversoeser Jul 18, 2025
96ab470
hyp split refactor
oliversoeser Jul 19, 2025
4ff5961
goal tracking refactor
oliversoeser Jul 19, 2025
5168049
simplify iApplyCore signature
oliversoeser Jul 19, 2025
cd95a81
PmTerms
oliversoeser Jul 19, 2025
671efb3
complete pmterm syntax
oliversoeser Jul 20, 2025
449575e
pmterm parser
oliversoeser Jul 20, 2025
8b40de9
fix pmterm ident type
oliversoeser Jul 20, 2025
2d51609
structure for recursive case
oliversoeser Jul 20, 2025
c0bf5c5
construction outline
oliversoeser Jul 20, 2025
a641db9
implement outline
oliversoeser Jul 20, 2025
0729e71
reworked iApply recursion
oliversoeser Jul 21, 2025
1b2ab36
experimental implementation
oliversoeser Jul 30, 2025
84ff33e
explicit instance construction
oliversoeser Jul 30, 2025
dc190de
working prototype
oliversoeser Jul 30, 2025
ed7eaee
goal tracker
oliversoeser Jul 30, 2025
f470641
weaken assumption theorem hypotheses
oliversoeser Jul 30, 2025
67a12a1
refactoring
oliversoeser Jul 31, 2025
f2c3aff
Merge branch 'master' into iapply
oliversoeser Jul 31, 2025
7e03b87
Revert "Merge branch 'master' into iapply"
oliversoeser Jul 31, 2025
013ad81
combine IntoWand and IntoWand'
oliversoeser Aug 1, 2025
daae14c
Merge branch 'leanprover-community:master' into iapply
oliversoeser Aug 1, 2025
5bb5655
get rid of RemoveHyp'
oliversoeser Aug 1, 2025
575122c
simplify iApplyCore and revert assumption
oliversoeser Aug 4, 2025
ea0815d
update lean
oliversoeser Aug 4, 2025
2d70845
fix pmterm parser
oliversoeser Aug 4, 2025
0decafa
simplify
oliversoeser Aug 4, 2025
1a12aa3
rec_apply
oliversoeser Aug 4, 2025
a2d75d3
additional test case
oliversoeser Aug 4, 2025
5d33ec0
more tests
oliversoeser Aug 4, 2025
a0803eb
restructure
oliversoeser Aug 4, 2025
6e7e912
lean lemma structure
oliversoeser Aug 4, 2025
51f67ce
prototype finished
oliversoeser Aug 4, 2025
c98b528
lean lemma exact case
oliversoeser Aug 5, 2025
2876ae7
comments
oliversoeser Aug 5, 2025
6954bdc
rename variables
oliversoeser Aug 5, 2025
4cd0647
lean lemma general case
oliversoeser Aug 6, 2025
3aed4ae
simplify
oliversoeser Aug 6, 2025
983d0fd
simplify
oliversoeser Aug 6, 2025
7961a91
add tests for lean lemma apply
oliversoeser Aug 6, 2025
8771eb7
rename temp
oliversoeser Aug 6, 2025
2629d95
eliminate trivial goals
oliversoeser Aug 6, 2025
fb38fd7
move goal elimination to core
oliversoeser Aug 6, 2025
3bb0d9b
adjust behaviour
oliversoeser Aug 6, 2025
52f2fe6
control goal elimination using with
oliversoeser Aug 6, 2025
5138d0d
nameable goals
oliversoeser Aug 6, 2025
8905208
add fromAssumption instances
oliversoeser Aug 7, 2025
2e93d34
headName
oliversoeser Aug 7, 2025
798da91
revert extra automation
oliversoeser Aug 7, 2025
9e3bac4
improve specpats
oliversoeser Aug 8, 2025
69c2b13
distinguish [H] and H
oliversoeser Aug 8, 2025
4e19bc2
restructure iApplyCore
oliversoeser Aug 8, 2025
ac460ba
proper error message
oliversoeser Aug 8, 2025
124e41d
ipose structure
oliversoeser Aug 8, 2025
9459f50
document iapply
oliversoeser Aug 8, 2025
f174afe
document specPat and pmTerm
oliversoeser Aug 8, 2025
b3e5307
fix test
oliversoeser Aug 8, 2025
d6a0adc
ipose prototype
oliversoeser Aug 11, 2025
2438131
ipose working
oliversoeser Aug 11, 2025
1c363fc
ipose emp case
oliversoeser Aug 11, 2025
9d1dca8
iPoseCore
oliversoeser Aug 11, 2025
0a76d07
ipose explicit types
oliversoeser Aug 11, 2025
ed00cbf
processSpecPats
oliversoeser Aug 11, 2025
8f3f32a
factor processSpecPats out of iApplyCore
oliversoeser Aug 12, 2025
9ffc891
more factoring
oliversoeser Aug 12, 2025
ba9eb70
specPatGoal
oliversoeser Aug 12, 2025
3270440
simplify recursive case
oliversoeser Aug 12, 2025
a8501a3
restructure ipose
oliversoeser Aug 12, 2025
dd7ff75
integrate ipose in iapply
oliversoeser Aug 12, 2025
d5fbfe3
simplify iApply
oliversoeser Aug 12, 2025
6d4a8ec
ipose refactor
oliversoeser Aug 12, 2025
fe13897
document ipose
oliversoeser Aug 12, 2025
dba0e6f
pmTerm syntax replace idents with terms
oliversoeser Aug 12, 2025
b5d9cc4
term cases and test
oliversoeser Aug 12, 2025
c2be0a7
fix
oliversoeser Aug 12, 2025
7f92909
Revert "fix"
oliversoeser Aug 12, 2025
0ac46ae
Revert "term cases and test"
oliversoeser Aug 12, 2025
ebc7bb6
blunt lean lemma application
oliversoeser Aug 13, 2025
b1c6760
combine and simplify
oliversoeser Aug 13, 2025
a4794c7
use of apply
oliversoeser Aug 13, 2025
f4d6c63
simplify
oliversoeser Aug 13, 2025
9cd8ae3
simplify
oliversoeser Aug 13, 2025
d88ffa0
exact term application
oliversoeser Aug 13, 2025
920b47f
working apply test
oliversoeser Aug 13, 2025
38c5ebb
refactor
oliversoeser Aug 13, 2025
bbd8c1e
ipose use identifiers
oliversoeser Aug 14, 2025
f897976
minor changes
oliversoeser Aug 14, 2025
30f0290
forall test
oliversoeser Aug 14, 2025
471877b
$! tests
oliversoeser Aug 18, 2025
2ab1377
basic $! functionality
oliversoeser Aug 18, 2025
62d30a5
Use IntoForall typeclass
oliversoeser Aug 19, 2025
e331f53
minor cleanup
oliversoeser Aug 19, 2025
a265544
update ipose description
oliversoeser Aug 19, 2025
1232e3e
$! working for iris hypotheses
oliversoeser Aug 19, 2025
d8addaf
IntoEmpValid
oliversoeser Aug 19, 2025
7e02499
refactor iPoseCore with IntoEmpValid
oliversoeser Aug 19, 2025
462048c
simplify single specPat
oliversoeser Aug 23, 2025
94479c2
handle top-level foralls
oliversoeser Sep 11, 2025
b6c4625
fully handle dependent arrows
oliversoeser Sep 11, 2025
e9f71b6
use iCasesCore in iPose
oliversoeser Sep 11, 2025
e050e0f
idents for goal naming
oliversoeser Sep 12, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions src/Iris/ProofMode/Classes.lean
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ declared as an `outParam`. Consequently, if type class instance search is suppos
`AsEmpValid2` is used.
-/

class AsEmpValid1 (φ : outParam Prop) {PROP : Type _} (P : PROP) [BI PROP] where
class AsEmpValid1 (φ : semiOutParam Prop) {PROP : Type _} (P : PROP) [BI PROP] where
as_emp_valid : φ ↔ ⊢ P

class AsEmpValid2 (φ : Prop) {PROP : outParam (Type _)} (P : outParam PROP) [BI PROP] where
Expand All @@ -40,6 +40,10 @@ proposition can be derived. Type classes with the prefix `Into` are used to gene
*into* which the original proposition can be turned by derivation. Additional boolean flags are
used to indicate that certain propositions should be intuitionistic. -/

class IntoEmpValid (φ : Prop) {PROP : outParam (Type _)} (P : outParam PROP) [BI PROP] where
into_emp_valid : φ → ⊢ P
export IntoEmpValid (into_emp_valid)

class FromImp [BI PROP] (P : PROP) (Q1 Q2 : outParam PROP) where
from_imp : (Q1 → Q2) ⊢ P
export FromImp (from_imp)
Expand All @@ -48,7 +52,7 @@ class FromWand [BI PROP] (P : PROP) (Q1 Q2 : outParam PROP) where
from_wand : (Q1 -∗ Q2) ⊢ P
export FromWand (from_wand)

class IntoWand [BI PROP] (p q : Bool) (R P : PROP) (Q : outParam PROP) where
class IntoWand [BI PROP] (p q : Bool) (R : PROP) (P Q : outParam PROP) where
into_wand : □?p R ⊢ □?q P -∗ Q
export IntoWand (into_wand)

Expand Down Expand Up @@ -106,7 +110,7 @@ class IntoAbsorbingly [BI PROP] (P : outParam PROP) (Q : PROP) where
export IntoAbsorbingly (into_absorbingly)


class FromAssumption (p : Bool) [BI PROP] (P Q : PROP) where
class FromAssumption (p : Bool) [BI PROP] (P : semiOutParam PROP) (Q : PROP) where
from_assumption : □?p P ⊢ Q
export FromAssumption (from_assumption)

Expand Down
18 changes: 18 additions & 0 deletions src/Iris/ProofMode/Instances.lean
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@ instance asEmpValid1_equiv [BI PROP] (P Q : PROP) : AsEmpValid1 (P ⊣⊢ Q) ipr
instance asEmpValid2_equiv [BI PROP] (P Q : PROP) : AsEmpValid2 (P ⊣⊢ Q) iprop(P ∗-∗ Q) :=
AsEmpValid1.to2

-- IntoEmpValid
instance intoEmpValid_emp_entails [BI PROP] (P : PROP) : IntoEmpValid (⊢ P) iprop(P) where
into_emp_valid := id

instance intoEmpValid_entails [BI PROP] (P Q : PROP) : IntoEmpValid (P ⊢ Q) iprop(P -∗ Q) where
into_emp_valid := entails_wand

instance intoEmpValid_equiv [BI PROP] (P Q : PROP) : IntoEmpValid (P ⊣⊢ Q) iprop(P ∗-∗ Q) where
into_emp_valid := equiv_wandIff

-- FromImp
instance fromImp_imp [BI PROP] (P1 P2 : PROP) : FromImp iprop(P1 → P2) P1 P2 := ⟨.rfl⟩
-- FromWand
Expand Down Expand Up @@ -67,6 +77,10 @@ instance intoWand_intuitionistically (p q : Bool) [BI PROP] (R P Q : PROP)
[h : IntoWand true q R P Q] : IntoWand p q iprop(□ R) P Q where
into_wand := (intuitionisticallyIf_mono h.1).trans intuitionisticallyIf_elim

instance intoWand_intuitionistically_wand (p : Bool) [BI PROP] (P Q : PROP) :
IntoWand p true iprop(□ P -∗ Q) P Q where
into_wand := intuitionisticallyIf_elim

instance intoWand_persistently_true (q : Bool) [BI PROP] (R P Q : PROP)
[h : IntoWand true q R P Q] : IntoWand true q iprop(<pers> R) P Q where
into_wand := intuitionistically_persistently.1.trans h.1
Expand Down Expand Up @@ -429,6 +443,10 @@ instance (priority := default + 10) fromAssumption_forall (p : Bool) [BI PROP] (
(x : α) (Q : PROP) [h : FromAssumption p (Φ x) Q] : FromAssumption p iprop(∀ x, Φ x) Q where
from_assumption := (intuitionisticallyIf_mono <| forall_elim x).trans h.1

instance fromAssumption_later [BI PROP] (p : Bool) (P Q : PROP)
[h : FromAssumption p P Q] : FromAssumption p P iprop(▷ Q) where
from_assumption := h.1.trans later_intro

-- IntoPure
instance intoPure_pure (φ : Prop) [BI PROP] : IntoPure (PROP := PROP) iprop(⌜φ⌝) φ := ⟨.rfl⟩

Expand Down
2 changes: 2 additions & 0 deletions src/Iris/ProofMode/Patterns.lean
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
import Iris.ProofMode.Patterns.CasesPattern
import Iris.ProofMode.Patterns.ProofModeTerm
import Iris.ProofMode.Patterns.SpecPattern
34 changes: 34 additions & 0 deletions src/Iris/ProofMode/Patterns/ProofModeTerm.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/-
Copyright (c) 2025 Oliver Soeser. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Oliver Soeser
-/
import Iris.ProofMode.Patterns.SpecPattern

namespace Iris.ProofMode
open Lean

declare_syntax_cat pmTerm

syntax term : pmTerm
syntax term "with" specPat,+ : pmTerm
syntax term "$!" term,+ : pmTerm
syntax term "$!" term,+ "with" specPat,+ : pmTerm
Comment on lines +13 to +16
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to leave this for now but I think it's worth putting on the todo list to improve this syntax, I think we can do better with a more curry howard application-like syntax.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moving this to an issue.


structure PMTerm where
term : Term
terms : List Term
spats : List SpecPat
deriving Repr, Inhabited

partial def PMTerm.parse (term : Syntax) : MacroM PMTerm := do
match ← expandMacros term with
| `(pmTerm| $trm:term) => return ⟨trm, [], []⟩
| `(pmTerm| $trm:term with $spats,*) => return ⟨trm, [], ← parseSpats spats⟩
| `(pmTerm| $trm:term $! $ts,*) => return ⟨trm, ts.getElems.toList, []⟩
| `(pmTerm| $trm:term $! $ts,* with $spats,*) =>
return ⟨trm, ts.getElems.toList, ← parseSpats spats⟩
| _ => Macro.throwUnsupported
where
parseSpats (spats : Syntax.TSepArray `specPat ",") : MacroM (List SpecPat) :=
return (← spats.getElems.toList.mapM fun pat => SpecPat.parse pat.raw)
36 changes: 36 additions & 0 deletions src/Iris/ProofMode/Patterns/SpecPattern.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/-
Copyright (c) 2025 Oliver Soeser. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Oliver Soeser
-/
namespace Iris.ProofMode
open Lean

declare_syntax_cat specPat

syntax binderIdent : specPat
syntax "[" binderIdent,* "]" optional(" as " ident) : specPat

inductive SpecPat
| ident (name : TSyntax ``binderIdent)
| idents (names : List (TSyntax ``binderIdent)) (goalName : Name)
deriving Repr, Inhabited

partial def SpecPat.parse (pat : Syntax) : MacroM SpecPat := do
match go ⟨← expandMacros pat⟩ with
| none => Macro.throwUnsupported
| some pat => return pat
where
go : TSyntax `specPat → Option SpecPat
| `(specPat| $name:binderIdent) => some <| .ident name
| `(specPat| [$[$names:binderIdent],*]) => some <| .idents names.toList .anonymous
| `(specPat| [$[$names:binderIdent],*] as $goal:ident) => match goal.raw with
| .ident _ _ val _ => some <| .idents names.toList val
| _ => none
| _ => none

def headName (spats : List SpecPat) : Name :=
match spats.head? with
| some <| .ident _ => .anonymous
| some <| .idents _ name => name
| _ => .anonymous
2 changes: 2 additions & 0 deletions src/Iris/ProofMode/Tactics.lean
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/- A description of the tactics can be found in `tactics.md`. -/
import Iris.ProofMode.Tactics.Apply
import Iris.ProofMode.Tactics.Assumption
import Iris.ProofMode.Tactics.Basic
import Iris.ProofMode.Tactics.Cases
Expand All @@ -9,6 +10,7 @@ import Iris.ProofMode.Tactics.Exists
import Iris.ProofMode.Tactics.Intro
import Iris.ProofMode.Tactics.LeftRight
import Iris.ProofMode.Tactics.Move
import Iris.ProofMode.Tactics.Pose
import Iris.ProofMode.Tactics.Pure
import Iris.ProofMode.Tactics.Remove
import Iris.ProofMode.Tactics.Rename
Expand Down
126 changes: 126 additions & 0 deletions src/Iris/ProofMode/Tactics/Apply.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/-
Copyright (c) 2025 Oliver Soeser. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Oliver Soeser
-/
import Iris.ProofMode.Patterns.ProofModeTerm
import Iris.ProofMode.Tactics.Split
import Iris.ProofMode.Tactics.Pose

namespace Iris.ProofMode
open Lean Elab Tactic Meta Qq BI Std

theorem apply [BI PROP] {P Q1 Q2 R : PROP}
(h : P ⊢ Q1) [inst : IntoWand false false R Q1 Q2] : P ∗ R ⊢ Q2 :=
(sep_mono h inst.1).trans wand_elim_r

theorem rec_apply [BI PROP] {P Q P' Q' Q1 Q2 R : PROP}
(h1 : P ⊣⊢ P' ∗ Q') (h2 : Q' ⊢ Q1) (h3 : P' ∗ Q2 ⊢ R)
[IntoWand false false Q Q1 Q2] : P ∗ Q ⊢ R :=
(sep_congr h1 .rfl).mp.trans <| sep_assoc.mp.trans <| (sep_mono_r <| apply h2).trans h3

theorem apply_lean [BI PROP] {P Q R : PROP} (h1 : ⊢ Q) (h2 : P ∗ Q ⊢ R) : P ⊢ R :=
sep_emp.mpr.trans <| (sep_mono_r h1).trans h2

variable {prop : Q(Type u)} {bi : Q(BI $prop)} in
def specPatGoal
(A1 : Q($prop)) (hyps : Hyps bi e) (spats : List SpecPat)
(addGoal : ∀ {e}, Name → Hyps bi e → (goal : Q($prop)) → MetaM Q($e ⊢ $goal)) :
MetaM Q($e ⊢ $A1) := do
return ← if let (some <| .ident _, some inst) := (spats.head?,
← try? (synthInstanceQ q(FromAssumption false $e $A1))) then
pure q(($inst).from_assumption)
else
addGoal (headName spats) hyps A1

variable {prop : Q(Type u)} {bi : Q(BI $prop)} in
def processSpecPats
(A1 : Q($prop)) (hypsl : Hyps bi el) (spats : List SpecPat)
(addGoal : ∀ {e}, Name → Hyps bi e → (goal : Q($prop)) → MetaM Q($e ⊢ $goal)) :
MetaM ((el' er' : Q($prop)) × Q($er' ⊢ $A1) × Hyps bi el' × Q($el ⊣⊢ $el' ∗ $er')) := do
let splitPat := fun name _ => match spats.head? with
| some <| .ident bIdent => binderIdentHasName name bIdent
| some <| .idents bIdents _ => bIdents.any <| binderIdentHasName name
| _ => false

let ⟨el', er', hypsl', hypsr', h'⟩ := Hyps.split bi splitPat hypsl
let m ← specPatGoal A1 hypsr' spats addGoal
return ⟨el', er', m, hypsl', h'⟩

variable {prop : Q(Type u)} {bi : Q(BI $prop)} in
partial def iApplyCore
(goal el er : Q($prop)) (hypsl : Hyps bi el) (spats : List SpecPat)
(addGoal : ∀ {e}, Name → Hyps bi e → (goal : Q($prop)) → MetaM Q($e ⊢ $goal)) :
MetaM (Q($el ∗ $er ⊢ $goal)) := do
let A1 ← mkFreshExprMVarQ q($prop)
let A2 ← mkFreshExprMVarQ q($prop)

let _ ← isDefEq er goal
if let (some _, some _) := (← try? <| synthInstanceQ q(FromAssumption false $er $goal),
← try? <| synthInstanceQ q(TCOr (Affine $el) (Absorbing $goal))) then
-- iexact case
return q(assumption (p := false) .rfl)
else if let some _ ← try? <| synthInstanceQ q(IntoWand false false $er $A1 $goal) then
-- iapply base case
let m ← specPatGoal A1 hypsl spats addGoal
return q(apply $m)
else if let some _ ← try? <| synthInstanceQ q(IntoWand false false $er $A1 $A2) then
-- iapply recursive case
let ⟨el', _, m, hypsl', h'⟩ ← processSpecPats A1 hypsl spats addGoal
let res : Q($el' ∗ $A2 ⊢ $goal) ← iApplyCore goal el' A2 hypsl' spats.tail addGoal
return q(rec_apply $h' $m $res)
else
throwError "iapply: cannot apply {er} to {goal}"

theorem apply_forall [BI PROP] (x : α) (P : α → PROP) {Q : PROP}
[H1 : IntoForall Q P] (H2 : E ⊢ E' ∗ Q) : E ⊢ E' ∗ P x :=
Entails.trans H2 <| sep_mono_r <| H1.into_forall.trans <| forall_elim x

partial def instantiateForalls' {prop : Q(Type u)} (e e' : Q($prop)) (bi : Q(BI $prop))
(out : Q($prop)) (pf : Q($e ⊢ $e' ∗ $out)) (terms : List Term) :
TacticM (Expr × Expr) := do
if let some t := terms.head? then
let texpr ← mkAppM' (← elabTerm t none) #[]
let ⟨_, ttype, texpr⟩ ← inferTypeQ texpr
let Φ ← mkFreshExprMVarQ q($ttype → $prop)
let _ ← synthInstanceQ q(IntoForall $out $Φ)
let res ← mkAppM' Φ #[texpr]
let pf' ← mkAppM ``apply_forall #[texpr, Φ, pf]
return ← instantiateForalls' e e' bi res pf' terms.tail
else
return ⟨out, pf⟩

elab "iapply" colGt pmt:pmTerm : tactic => do
let pmt ← liftMacroM <| PMTerm.parse pmt
let mvar ← getMainGoal

mvar.withContext do
let g ← instantiateMVars <| ← mvar.getType
let some { u, prop, e, bi, hyps, goal, .. } := parseIrisGoal? g | throwError "not in proof mode"
if let some uniq ← try? do pure (← hyps.findWithInfo ⟨pmt.term⟩) then
-- lemma from iris context
let ⟨e', hyps', out, _, _, _, pf⟩ := hyps.remove false uniq

let ⟨out, pf⟩ := ← instantiateForalls' e e' bi out q(($pf).mp) pmt.terms

let goals ← IO.mkRef #[]
let res ← iApplyCore goal e' out hyps' pmt.spats <| goalTracker goals
mvar.assign <| ← mkAppM ``Entails.trans #[pf, res]
replaceMainGoal (← goals.get).toList
else
-- lemma from lean context
let A1 ← mkFreshExprMVarQ q($prop)
let A2 ← mkFreshExprMVarQ q($prop)

let expected : Q(Prop) := if let some _ := ← try? <|
synthInstanceQ q(IntoWand false false $goal $A1 $A2)
then q($e ⊢ $A1 -∗ $A2) else q($e ⊢ $goal)

let expr ← mkAppM' (← elabTerm pmt.term (some expected)) #[]

let goals ← IO.mkRef #[]
let ⟨hyp, pf⟩ ← iPoseCore bi expr pmt.terms goals

let res ← iApplyCore goal e hyp hyps pmt.spats <| goalTracker goals
mvar.assign <| ← mkAppM ``apply_lean #[pf, res]
replaceMainGoal (← goals.get).toList
14 changes: 14 additions & 0 deletions src/Iris/ProofMode/Tactics/Basic.lean
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,23 @@ def getFreshName : TSyntax ``binderIdent → CoreM (Name × Syntax)
| `(binderIdent| $name:ident) => pure (name.getId, name)
| stx => return (← mkFreshUserName `x, stx)

def binderIdentHasName (name : Name) (id : TSyntax ``binderIdent) : Bool :=
match id with
| `(binderIdent| $name':ident) => name'.getId == name
| _ => false

def selectHyp (ty : Expr) : ∀ {s}, @Hyps u prop bi s → MetaM (Name × Q(Bool) × Q($prop))
| _, .emp _ => failure
| _, .hyp _ _ uniq p ty' _ => do
let .true ← isDefEq ty ty' | failure
pure (uniq, p, ty')
| _, .sep _ _ _ _ lhs rhs => try selectHyp ty rhs catch _ => selectHyp ty lhs

variable {prop : Q(Type u)} {bi : Q(BI $prop)} in
def goalTracker {P} (goals : IO.Ref (Array MVarId)) (name : Name) (hyps : Hyps bi P)
(goal : Q($prop)) : MetaM Q($P ⊢ $goal) := do
let m : Q($P ⊢ $goal) ← mkFreshExprSyntheticOpaqueMVar <|
IrisGoal.toExpr { prop, bi, hyps, goal, .. }
m.mvarId!.setUserName name
goals.modify (·.push m.mvarId!)
pure m
6 changes: 1 addition & 5 deletions src/Iris/ProofMode/Tactics/Cases.lean
Original file line number Diff line number Diff line change
Expand Up @@ -286,11 +286,7 @@ elab "icases" colGt hyp:ident "with" colGt pat:icasesPat : tactic => do

-- process pattern
let goals ← IO.mkRef #[]
let pf2 ← iCasesCore bi hyps' goal b A A' h pat fun hyps => do
let m : Q($e ⊢ $goal) ← mkFreshExprSyntheticOpaqueMVar <|
IrisGoal.toExpr { u, prop, bi, hyps, goal, .. }
goals.modify (·.push m.mvarId!)
pure m
let pf2 ← iCasesCore bi hyps' goal b A A' h pat (λ hyps => goalTracker goals .anonymous hyps goal)

mvar.assign q(($pf).1.trans $pf2)
replaceMainGoal (← goals.get).toList
8 changes: 2 additions & 6 deletions src/Iris/ProofMode/Tactics/Intro.lean
Original file line number Diff line number Diff line change
Expand Up @@ -102,16 +102,12 @@ elab "iintro" pats:(colGt icasesPat)* : tactic => do
-- parse syntax
let pats ← liftMacroM <| pats.mapM <| iCasesPat.parse

let (mvar, { prop, bi, hyps, goal, .. }) ← istart (← getMainGoal)
let (mvar, { bi, hyps, goal, .. }) ← istart (← getMainGoal)
mvar.withContext do

-- process patterns
let goals ← IO.mkRef #[]
let pf ← iIntroCore bi hyps goal pats.toList fun {P} hyps goal => do
let m : Q($P ⊢ $goal) ← mkFreshExprSyntheticOpaqueMVar <|
IrisGoal.toExpr { prop, bi, hyps, goal, .. }
goals.modify (·.push m.mvarId!)
pure m
let pf ← iIntroCore bi hyps goal pats.toList <| goalTracker goals .anonymous

mvar.assign pf
replaceMainGoal (← goals.get).toList
Loading