@@ -3,6 +3,7 @@ import Auto.Lib.BoolExtra
33import Auto.Lib.MessageData
44import Auto.Lib.ExprExtra
55import Auto.Lib.ListExtra
6+ import Auto.Lib.MetaExtra
67import Auto.Lib.Containers
78import Auto.Lib.AbstractMVars
89open Lean
@@ -122,20 +123,29 @@ def Lemma.reorderForallInstDep (lem : Lemma) : MetaM Lemma := do
122123 · If `lhs` occurs in `lem.type`, perform rewrite and return result
123124 · If `lhs` does not occur in `lem.type`, return `.none`
124125-/
125- def Lemma.rewriteUMonoRigid? (lem : Lemma) (rw : UMonoFact) : MetaM (Option Lemma) := do
126+ def Lemma.rewriteUMonoRigid? (lem : Lemma) (rw : UMonoFact) (nonDep : Bool) : MetaM (Option Lemma) := do
126127 let ⟨rwproof, rwtype, rwDeriv⟩ := rw
127128 let .some (α, lhs, rhs) ← Meta.matchEq? rwtype
128129 | throwError "{decl_name%} :: {rwtype} is not an equality"
129130 let ⟨⟨proof, e, lemDeriv⟩, params⟩ := lem
130- let eAbst ← Meta.kabstract e lhs
131+ let eAbst ← (do
132+ if nonDep then
133+ Meta.withLocalDeclD `_a α fun x => do return (← Meta.replaceNonDep e lhs x).abstract #[x]
134+ else Meta.kabstract e lhs)
131135 unless eAbst.hasLooseBVars do
132136 return .none
133137 let eNew := eAbst.instantiate1 rhs
134138 let motive := mkLambda `_a BinderInfo.default α eAbst
135139 unless (← Meta.isTypeCorrect motive) do
136140 throwError "{decl_name%} :: Motive {motive} is not type correct"
137141 let eqPrf ← Meta.mkEqNDRec motive proof rwproof
138- return .some ⟨⟨eqPrf, eNew, .node "rw" #[lemDeriv, rwDeriv]⟩, params⟩
142+ return .some ⟨⟨eqPrf, ← Core.betaReduce eNew, .node "rw" #[lemDeriv, rwDeriv]⟩, params⟩
143+
144+ def checkNonRecEquality (e : Expr) : MetaM Unit := do
145+ let .some (_, lhs, rhs) ← Meta.matchEq? e
146+ | throwError "{decl_name%} :: {e} is not an equality"
147+ if (← Meta.kabstract rhs lhs).hasLooseBVars then
148+ throwError "{decl_name%} :: Right-hand side {rhs} of equality contains left-hand side {lhs}"
139149
140150/--
141151 Exhaustively rewrite using a universe-polymorphic rigid equality
@@ -147,19 +157,16 @@ def Lemma.rewriteUMonoRigid? (lem : Lemma) (rw : UMonoFact) : MetaM (Option Lemm
147157def Lemma.rewriteUPolyRigid (lem : Lemma) (rw : Lemma) : MetaM Lemma := do
148158 let mut lem := lem
149159 let s ← saveState
150- -- Test whether `rhs` contains `lhs
151- let .some (_, lhs, rhs) ← Meta.matchEq? rw.type
152- | throwError "{decl_name%} :: {rw.type} is not an equality"
153- let lhs' := lhs.instantiateLevelParamsArray rw.params (← rw.params.mapM (fun _ => Meta.mkFreshLevelMVar))
154- let rhs' := rhs.instantiateLevelParamsArray rw.params (← rw.params.mapM (fun _ => Meta.mkFreshLevelMVar))
155- if (← Meta.kabstract rhs' lhs').hasLooseBVars then
156- throwError "{decl_name%} :: Right-hand side {rhs} of equality contains left-hand side {lhs}"
160+ -- Test whether `rhs` contains `lhs`
161+ let rwty' := rw.type.instantiateLevelParamsArray
162+ rw.params (← rw.params.mapM (fun _ => Meta.mkFreshLevelMVar))
163+ checkNonRecEquality rwty'
157164 restoreState s
158165 while true do
159166 let umvars ← rw.params.mapM (fun _ => Meta.mkFreshLevelMVar)
160167 let .some urw := (rw.instantiateLevelParamsArray umvars).toUMonoFact?
161168 | throwError "{decl_name%} :: Unexpected error"
162- let .some lem' ← Lemma.rewriteUMonoRigid? lem urw
169+ let .some lem' ← Lemma.rewriteUMonoRigid? lem urw false
163170 | break
164171 let restmvars := (← umvars.mapM Level.collectLevelMVars).flatMap id
165172 for lmvar in restmvars do
@@ -169,6 +176,41 @@ def Lemma.rewriteUPolyRigid (lem : Lemma) (rw : Lemma) : MetaM Lemma := do
169176 restoreState s
170177 return ← lem.betaReduceType
171178
179+ /--
180+ Exhaustively rewrite using an array of universe-polymorphic rigid equalities
181+ · Only `lhs`s occurring in non-dependent positions will be replaced by `rhs`
182+ · If there are multiple instances of `lhs` with different universe
183+ level instantiations, all of these instances will be replaced with `rhs`
184+ · `rw.snd` should have the form `lhs = rhs`, where both sides are rigid
185+ and `rhs` should not contain `lhs`
186+ -/
187+ def Lemma.rewriteUPolyRigidNonDep (lem : Lemma) (rws : Array Lemma) : MetaM Lemma := do
188+ let mut lem := lem
189+ let s ← saveState
190+ -- Test whether `rhs` contains `lhs`
191+ for rw in rws do
192+ let rwty' := rw.type.instantiateLevelParamsArray
193+ rw.params (← rw.params.mapM (fun _ => Meta.mkFreshLevelMVar))
194+ checkNonRecEquality rwty'
195+ restoreState s
196+ while true do
197+ let lemRef := lem
198+ for rw in rws do
199+ let umvars ← rw.params.mapM (fun _ => Meta.mkFreshLevelMVar)
200+ let .some urw := (rw.instantiateLevelParamsArray umvars).toUMonoFact?
201+ | throwError "{decl_name%} :: Unexpected error"
202+ let .some lem' ← Lemma.rewriteUMonoRigid? lem urw true
203+ | continue
204+ let restmvars := (← umvars.mapM Level.collectLevelMVars).flatMap id
205+ for lmvar in restmvars do
206+ if !(← Meta.isLevelDefEq (.mvar lmvar) .zero) then
207+ break
208+ lem ← lem'.instantiateMVars
209+ if lem == lemRef then
210+ break
211+ restoreState s
212+ return lem
213+
172214/-
173215 An instance of a `Lemma`. If a lemma has proof `H`,
174216 then an instance of the lemma would be like
0 commit comments