@@ -5,7 +5,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
55Authors: Abdalrhman Mohamed, Tomaz Gomes Mascarenhas
66-/
77
8- import Lean
8+ import Smt.Preprocess.Basic
99import Qq
1010
1111namespace Smt.Preprocess
@@ -27,43 +27,46 @@ def replaceIff (e : Expr) : MetaM Expr :=
2727def containsIff (e : Expr) : Bool :=
2828 (Expr.const ``Iff []).occurs e
2929
30- def elimIff (mv : MVarId) (hs : List Expr) : MetaM (List Expr × MVarId) := mv.withContext do
30+ def elimIff (mv : MVarId) (hs : Array Expr) : MetaM Result := mv.withContext do
3131 let t ← instantiateMVars (← mv.getType)
3232 let ts ← hs.mapM (Meta.inferType · >>= instantiateMVars)
3333 if !(containsIff t || ts.any containsIff) then
34- return (hs, mv)
34+ return { map := Std.HashMap.insertMany ∅ (hs.zip (hs.map .singleton)), hs, mv }
3535 let simpTheorems ← #[``eq_self, ``iff_eq_eq].foldlM (·.addConst ·) ({} : Meta.SimpTheorems)
3636 let simpTheorems := #[simpTheorems]
3737 let congrTheorems ← Meta.getSimpCongrTheorems
3838 let ctx ← Meta.Simp.mkContext {} simpTheorems congrTheorems
39- let (hs, mv) ← elimIffLocalDecls mv hs ctx
40- let mv ← elimIffTarget mv ctx
41- return (hs, mv)
39+ let (hs' , mv' ) ← elimIffLocalDecls mv hs.toList ctx #[]
40+ let mv' ← elimIffTarget mv' ctx
41+ return { map := Std.HashMap.insertMany ∅ (hs'.zip (hs.map .singleton)), hs := hs', mv := mv' }
4242where
43- elimIffLocalDecls mv hs ctx := mv.withContext do
44- let mut newHs := []
45- let mut toAssert := #[]
46- for h in hs do
43+ elimIffLocalDecls mv hs ctx hs' := do match hs with
44+ | [] => return (hs', mv)
45+ | h :: hs =>
4746 let type ← Meta.inferType h
4847 let eq ← replaceIff (← instantiateMVars type)
4948 let (_, l, r) := eq.eq?.get!
5049 if l == r then
51- newHs := h :: newHs
50+ elimIffLocalDecls mv hs ctx (hs'.push h)
5251 else
53- let userName ← if h.isFVar then h.fvarId!.getUserName else Lean.mkFreshId
54- let type := r
55- let (r, _) ← Meta.simp eq ctx
56- let value ← Meta.mkAppM ``eq_resolve #[h, ← Meta.mkOfEqTrue (← r.getProof)]
57- toAssert := toAssert.push { userName, type, value }
58- let (fvs, mv) ← mv.assertHypotheses toAssert
59- newHs := newHs.reverse ++ (fvs.map (.fvar ·)).toList
60- return (newHs, mv)
52+ let (res, _) ← Meta.simp eq ctx
53+ let h' := mkApp4 (.const ``eq_resolve []) l r h (mkOfEqTrue eq (← res.getProof))
54+ if let .some fv := h.fvarId? then
55+ let res ← mv.replace fv h' (.some r)
56+ let hs' := hs'.map res.subst.apply
57+ let hs := hs.map res.subst.apply
58+ res.mvarId.withContext (elimIffLocalDecls res.mvarId hs ctx (hs'.push (.fvar res.fvarId)))
59+ else
60+ elimIffLocalDecls mv hs ctx (hs'.push h')
61+ termination_by hs.length
6162 elimIffTarget mv ctx := mv.withContext do
6263 let eq ← replaceIff (← instantiateMVars (← mv.getType))
63- let (r , _) ← Meta.simp eq ctx
64- if r .expr.isTrue then
65- mv.replaceTargetEq eq.appArg! (← Meta. mkOfEqTrue (← r .getProof))
64+ let (res , _) ← Meta.simp eq ctx
65+ if res .expr.isTrue then
66+ mv.replaceTargetEq eq.appArg! (mkOfEqTrue eq (← res .getProof))
6667 else
6768 return mv
69+ mkOfEqTrue p hpt :=
70+ mkApp2 (.const ``of_eq_true []) p hpt
6871
6972end Smt.Preprocess
0 commit comments