lean4-htt/src/Lean/Meta/Tactic/Assert.lean
2021-03-19 19:54:22 -07:00

109 lines
4.8 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/-
Copyright (c) 2020 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
import Lean.Meta.Tactic.Util
import Lean.Meta.Tactic.FVarSubst
import Lean.Meta.Tactic.Intro
import Lean.Meta.Tactic.Revert
namespace Lean.Meta
/--
Convert the given goal `Ctx |- target` into `Ctx |- type -> target`.
It assumes `val` has type `type` -/
def assert (mvarId : MVarId) (name : Name) (type : Expr) (val : Expr) : MetaM MVarId :=
withMVarContext mvarId do
checkNotAssigned mvarId `assert
let tag ← getMVarTag mvarId
let target ← getMVarType mvarId
let newType := Lean.mkForall name BinderInfo.default type target
let newMVar ← mkFreshExprSyntheticOpaqueMVar newType tag
assignExprMVar mvarId (mkApp newMVar val)
pure newMVar.mvarId!
/--
Convert the given goal `Ctx |- target` into `Ctx |- let name : type := val; target`.
It assumes `val` has type `type` -/
def define (mvarId : MVarId) (name : Name) (type : Expr) (val : Expr) : MetaM MVarId := do
withMVarContext mvarId do
checkNotAssigned mvarId `define
let tag ← getMVarTag mvarId
let target ← getMVarType mvarId
let newType := Lean.mkLet name type val target
let newMVar ← mkFreshExprSyntheticOpaqueMVar newType tag
assignExprMVar mvarId newMVar
pure newMVar.mvarId!
/--
Convert the given goal `Ctx |- target` into `Ctx |- (hName : type) -> hName = val -> target`.
It assumes `val` has type `type` -/
def assertExt (mvarId : MVarId) (name : Name) (type : Expr) (val : Expr) (hName : Name := `h) : MetaM MVarId := do
withMVarContext mvarId do
checkNotAssigned mvarId `assert
let tag ← getMVarTag mvarId
let target ← getMVarType mvarId
let u ← getLevel type
let hType := mkApp3 (mkConst `Eq [u]) type (mkBVar 0) val
let newType := Lean.mkForall name BinderInfo.default type $ Lean.mkForall hName BinderInfo.default hType target
let newMVar ← mkFreshExprSyntheticOpaqueMVar newType tag
let rflPrf ← mkEqRefl val
assignExprMVar mvarId (mkApp2 newMVar val rflPrf)
pure newMVar.mvarId!
structure AssertAfterResult where
fvarId : FVarId
mvarId : MVarId
subst : FVarSubst
/--
Convert the given goal `Ctx |- target` into a goal containing `(userName : type)` after the local declaration with if `fvarId`.
It assumes `val` has type `type`, and that `type` is well-formed after `fvarId`.
Note that `val` does not need to be well-formed after `fvarId`. That is, it may contain variables that are defined after `fvarId`. -/
def assertAfter (mvarId : MVarId) (fvarId : FVarId) (userName : Name) (type : Expr) (val : Expr) : MetaM AssertAfterResult := do
withMVarContext mvarId do
checkNotAssigned mvarId `assertAfter
let tag ← getMVarTag mvarId
let target ← getMVarType mvarId
let localDecl ← getLocalDecl fvarId
let lctx ← getLCtx
let localInsts ← getLocalInstances
let fvarIds := lctx.foldl (init := #[]) (start := localDecl.index+1) fun fvarIds decl => fvarIds.push decl.fvarId
let xs := fvarIds.map mkFVar
let targetNew ← mkForallFVars xs target (usedLetOnly := false)
let targetNew := Lean.mkForall userName BinderInfo.default type targetNew
let lctxNew := fvarIds.foldl (init := lctx) fun lctxNew fvarId => lctxNew.erase fvarId
let localInstsNew := localInsts.filter fun inst => !fvarIds.contains inst.fvar.fvarId!
let mvarNew ← mkFreshExprMVarAt lctxNew localInstsNew targetNew MetavarKind.syntheticOpaque tag
let args := (fvarIds.filter fun fvarId => !(lctx.get! fvarId).isLet).map mkFVar
let args := #[val] ++ args
assignExprMVar mvarId (mkAppN mvarNew args)
let (fvarIdNew, mvarIdNew) ← intro1P mvarNew.mvarId!
let (fvarIdsNew, mvarIdNew) ← introNP mvarIdNew fvarIds.size
let subst := fvarIds.size.fold (init := {}) fun i subst => subst.insert fvarIds[i] (mkFVar fvarIdsNew[i])
pure { fvarId := fvarIdNew, mvarId := mvarIdNew, subst := subst }
structure Hypothesis where
userName : Name
type : Expr
value : Expr
/--
Convert the given goal `Ctx |- target` into `Ctx, (hs[0].userName : hs[0].type) ... |-target`.
It assumes `hs[i].val` has type `hs[i].type`. -/
def assertHypotheses (mvarId : MVarId) (hs : Array Hypothesis) : MetaM (Array FVarId × MVarId) := do
if hs.isEmpty then
return (#[], mvarId)
else withMVarContext mvarId do
checkNotAssigned mvarId `assertHypotheses
let tag ← getMVarTag mvarId
let target ← getMVarType mvarId
let targetNew := hs.foldr (init := target) fun h targetNew =>
mkForall h.userName BinderInfo.default h.type targetNew
let mvarNew ← mkFreshExprSyntheticOpaqueMVar targetNew tag
let val := hs.foldl (init := mvarNew) fun val h => mkApp val h.value
assignExprMVar mvarId val
introNP mvarNew.mvarId! hs.size
end Lean.Meta