feat: add generalize and replaceLocalDecl

This commit is contained in:
Leonardo de Moura 2020-02-14 20:06:56 -08:00
parent 203bf08339
commit 9e68c1e1c6
8 changed files with 74 additions and 5 deletions

View file

@ -202,5 +202,11 @@ else do
pure $ mkAppN (mkConst `Eq.rec [u1, u2]) #[α, a, motive, h1, b, h2]
| _ => throwEx $ Exception.appBuilder `Eq.rec "invalid motive" #[motive]
def mkEqMP (eqProof pr : Expr) : MetaM Expr :=
mkAppM `Eq.mp #[eqProof, pr]
def mkEqMPR (eqProof pr : Expr) : MetaM Expr :=
mkAppM `Eq.mpr #[eqProof, pr]
end Meta
end Lean

View file

@ -189,8 +189,7 @@ numPostponed ← getNumPostponed;
if numPostponed == 0 then pure true
else traceCtx `Meta.isLevelDefEq.postponed $ processPostponedAux ()
private def restore (env : Environment) (mctx : MetavarContext) (postponed : PersistentArray PostponedEntry) : MetaM Unit :=
def restore (env : Environment) (mctx : MetavarContext) (postponed : PersistentArray PostponedEntry) : MetaM Unit :=
modify $ fun s => { env := env, mctx := mctx, postponed := postponed, .. s }
/--

View file

@ -12,3 +12,5 @@ import Init.Lean.Meta.Tactic.Clear
import Init.Lean.Meta.Tactic.Assert
import Init.Lean.Meta.Tactic.Target
import Init.Lean.Meta.Tactic.Rewrite
import Init.Lean.Meta.Tactic.Generalize
import Init.Lean.Meta.Tactic.LocalDecl

View file

@ -0,0 +1,31 @@
/-
Copyright (c) 2020 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
prelude
import Init.Lean.Meta.KAbstract
import Init.Lean.Meta.Tactic.Util
namespace Lean
namespace Meta
def generalize (mvarId : MVarId) (e : Expr) (x : Name) : MetaM MVarId := do
withMVarContext mvarId $ do
checkNotAssigned mvarId `generalize;
tag ← getMVarTag mvarId;
target ← getMVarType mvarId;
target ← instantiateMVars target;
targetAbst ← kabstract target e;
unless targetAbst.hasLooseBVars $
throwTacticEx `generalize mvarId ("failed to find expression in the target");
eType ← inferType e;
let targetNew := Lean.mkForall x BinderInfo.default eType targetAbst;
unlessM (isTypeCorrect targetNew) $
throwTacticEx `generalize mvarId ("result is not type correct");
mvarNew ← mkFreshExprSyntheticOpaqueMVar targetNew tag;
assignExprMVar mvarId (mkApp mvarNew e);
pure mvarNew.mvarId!
end Meta
end Lean

View file

@ -68,8 +68,8 @@ def intro (mvarId : MVarId) (name : Name) : MetaM (FVarId × MVarId) := do
(fvarIds, mvarId) ← introN mvarId 1 [name];
pure (fvarIds.get! 0, mvarId)
def intro1 (mvarId : MVarId) : MetaM (FVarId × MVarId) := do
(fvarIds, mvarId) ← introN mvarId 1 [];
def intro1 (mvarId : MVarId) (useUnusedNames := true) : MetaM (FVarId × MVarId) := do
(fvarIds, mvarId) ← introN mvarId 1 [] useUnusedNames;
pure (fvarIds.get! 0, mvarId)
end Meta

View file

@ -0,0 +1,25 @@
/-
Copyright (c) 2020 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
prelude
import Init.Lean.Meta.AppBuilder
import Init.Lean.Meta.Tactic.Util
import Init.Lean.Meta.Tactic.Assert
import Init.Lean.Meta.Tactic.Intro
import Init.Lean.Meta.Tactic.Clear
namespace Lean
namespace Meta
def replaceLocalDecl (mvarId : MVarId) (fvarId : FVarId) (newType : Expr) (eqProof : Expr) : MetaM (FVarId × MVarId) := do
withMVarContext mvarId $ do
localDecl ← getLocalDecl fvarId;
newTypePr ← mkEqMP eqProof (mkFVar fvarId);
mvarId ← assert mvarId localDecl.userName newType newTypePr;
(fvarIdNew, mvarId) ← intro1 mvarId;
(do mvarId ← clear mvarId fvarId; pure (fvarIdNew, mvarId)) <|> pure (fvarIdNew, mvarId)
end Meta
end Lean

View file

@ -40,7 +40,7 @@ withMVarContext mvarId $ do
eEqE ← mkEq e e;
let eEqEAbst := mkApp eEqE.appFn! eAbst;
let motive := Lean.mkLambda `_a BinderInfo.default α eEqEAbst;
unlessM (withAtLeastTransparency TransparencyMode.default $ isTypeCorrect motive) $
unlessM (isTypeCorrect motive) $
throwTacticEx `rewrite mvarId ("motive is not type correct");
eqRefl ← mkEqRefl e;
eqPrf ← mkEqNDRec motive eqRefl heq;

View file

@ -5,6 +5,7 @@ Authors: Leonardo de Moura
-/
prelude
import Init.Lean.Meta.Basic
import Init.Lean.Meta.LevelDefEq
namespace Lean
namespace Meta
@ -36,6 +37,11 @@ mctx ← getMCtx;
opts ← getOptions;
pure $ ppGoal env mctx opts mvarId
@[inline] protected def orelse{α} (x y : MetaM α) : MetaM α := do
s ← get; catch x (fun _ => do restore s.env s.mctx s.postponed; y)
instance Meta.hasOrelse {α} : HasOrelse (MetaM α) := ⟨Meta.orelse⟩
@[init] private def regTraceClasses : IO Unit :=
registerTraceClass `Meta.Tactic