Skip to content

Commit 11a6e57

Browse files
committed
Index.RulePattern: optimize for empty index
Rule pattern matching is quite expensive because we iterate over all expressions in the goal. This commit makes sure that when the index is empty, no matching takes place, so users who don't need rule patterns aren't unnecessarily penalised.
1 parent 3137f1f commit 11a6e57

File tree

1 file changed

+19
-3
lines changed

1 file changed

+19
-3
lines changed

Aesop/Index/RulePattern.lean

+19-3
Original file line numberDiff line numberDiff line change
@@ -58,29 +58,39 @@ set_option linter.missingDocs false in
5858
/-- A rule pattern index. Maps expressions `e` to rule patterns that likely
5959
unify with `e`. -/
6060
structure RulePatternIndex where
61+
/-- The index. -/
6162
tree : DiscrTree RulePatternIndex.Entry
63+
/-- `true` iff the index contains no patterns. -/
64+
isEmpty : Bool
6265
deriving Inhabited
6366

6467
namespace RulePatternIndex
6568

6669
instance : EmptyCollection RulePatternIndex :=
67-
⟨⟨{}⟩⟩
70+
⟨⟨{}, true⟩⟩
6871

6972
/-- Add a rule pattern to the index. -/
7073
def add (name : RuleName) (pattern : RulePattern) (idx : RulePatternIndex) :
7174
RulePatternIndex :=
72-
⟨idx.tree.insertCore pattern.discrTreeKeys { name, pattern }⟩
75+
⟨idx.tree.insertCore pattern.discrTreeKeys { name, pattern }, false
7376

7477
/-- Merge two rule pattern indices. Patterns that appear in both indices appear
7578
twice in the result. -/
7679
def merge (idx₁ idx₂ : RulePatternIndex) : RulePatternIndex :=
77-
⟨idx₁.tree.mergePreservingDuplicates idx₂.tree⟩
80+
if idx₁.isEmpty then
81+
idx₂
82+
else if idx₂.isEmpty then
83+
idx₁
84+
else
85+
⟨idx₁.tree.mergePreservingDuplicates idx₂.tree, false
7886

7987
section Get
8088

8189
/-- Get rule pattern substitutions for the patterns that match `e`. -/
8290
def getSingle (e : Expr) (idx : RulePatternIndex) :
8391
BaseM (Array (RuleName × Substitution)) := do
92+
if idx.isEmpty then
93+
return #[]
8494
let ms ← getUnify idx.tree e
8595
ms.filterMapM λ { name := r, pattern } => do
8696
let some subst ← pattern.match e
@@ -92,6 +102,8 @@ def getSingle (e : Expr) (idx : RulePatternIndex) :
92102
array may contain duplicates. -/
93103
def getCore (e : Expr) (idx : RulePatternIndex) :
94104
BaseM (Array (RuleName × Substitution)) := do
105+
if idx.isEmpty then
106+
return #[]
95107
let e ← instantiateMVars e
96108
checkCache (β := RulePatternCache.Entry) e λ _ => do
97109
let (_, ms) ← e.forEach getSubexpr |>.run #[]
@@ -118,6 +130,8 @@ the given local declaration. Subexpressions containing bound variables are not
118130
considered. -/
119131
def getInLocalDeclCore (acc : RulePatternSubstMap) (ldecl : LocalDecl)
120132
(idx : RulePatternIndex) : BaseM RulePatternSubstMap := do
133+
if idx.isEmpty then
134+
return acc
121135
let mut result := acc
122136
result := result.insertArray $ ← idx.getCore ldecl.toExpr
123137
result := result.insertArray $ ← idx.getCore ldecl.type
@@ -136,6 +150,8 @@ considered. -/
136150
def getInGoal (goal : MVarId) (idx : RulePatternIndex) :
137151
BaseM RulePatternSubstMap :=
138152
goal.withContext do
153+
if idx.isEmpty then
154+
return
139155
let mut result := ∅
140156
for ldecl in (← goal.getDecl).lctx do
141157
unless ldecl.isImplementationDetail do

0 commit comments

Comments
 (0)