refactor: add annotation for displaying conv state
This commit is contained in:
parent
a8b434f93d
commit
391366ef24
8 changed files with 32 additions and 31 deletions
|
|
@ -78,7 +78,6 @@ structure TacticInfo extends ElabInfo where
|
|||
goalsBefore : List MVarId
|
||||
mctxAfter : MetavarContext
|
||||
goalsAfter : List MVarId
|
||||
inConv : Bool
|
||||
deriving Inhabited
|
||||
|
||||
structure MacroExpansionInfo where
|
||||
|
|
@ -189,17 +188,17 @@ def FieldInfo.format (ctx : ContextInfo) (info : FieldInfo) : IO Format := do
|
|||
ctx.runMetaM info.lctx do
|
||||
return f!"{info.fieldName} : {← Meta.ppExpr (← Meta.inferType info.val)} := {← Meta.ppExpr info.val} @ {formatStxRange ctx info.stx}"
|
||||
|
||||
def ContextInfo.ppGoals (ctx : ContextInfo) (goals : List MVarId) (inConv : Bool) : IO Format :=
|
||||
def ContextInfo.ppGoals (ctx : ContextInfo) (goals : List MVarId) : IO Format :=
|
||||
if goals.isEmpty then
|
||||
return "no goals"
|
||||
else
|
||||
ctx.runMetaM {} (return Std.Format.prefixJoin "\n" (← goals.mapM (Meta.ppGoal . inConv)))
|
||||
ctx.runMetaM {} (return Std.Format.prefixJoin "\n" (← goals.mapM (Meta.ppGoal .)))
|
||||
|
||||
def TacticInfo.format (ctx : ContextInfo) (info : TacticInfo) : IO Format := do
|
||||
let ctxB := { ctx with mctx := info.mctxBefore }
|
||||
let ctxA := { ctx with mctx := info.mctxAfter }
|
||||
let goalsBefore ← ctxB.ppGoals info.goalsBefore info.inConv
|
||||
let goalsAfter ← ctxA.ppGoals info.goalsAfter info.inConv
|
||||
let goalsBefore ← ctxB.ppGoals info.goalsBefore
|
||||
let goalsAfter ← ctxA.ppGoals info.goalsAfter
|
||||
return f!"Tactic @ {formatElabInfo ctx info.toElabInfo}\n{info.stx}\nbefore {goalsBefore}\nafter {goalsAfter}"
|
||||
|
||||
def MacroExpansionInfo.format (ctx : ContextInfo) (info : MacroExpansionInfo) : IO Format := do
|
||||
|
|
|
|||
|
|
@ -39,8 +39,6 @@ structure Context where
|
|||
main : MVarId
|
||||
-- declaration name of the executing elaborator, used by `mkTacticInfo` to persist it in the info tree
|
||||
elaborator : Name
|
||||
-- `true` when in `conv` tactic mode. This flag is only used to pretty print the goals showing just the left-hand-side
|
||||
inConv : Bool := false
|
||||
|
||||
structure State where
|
||||
goals : List MVarId
|
||||
|
|
@ -121,7 +119,6 @@ def mkTacticInfo (mctxBefore : MetavarContext) (goalsBefore : List MVarId) (stx
|
|||
stx := stx
|
||||
mctxAfter := (← getMCtx)
|
||||
goalsAfter := (← getUnsolvedGoals)
|
||||
inConv := (← read).inConv
|
||||
}
|
||||
|
||||
def mkInitialTacticInfo (stx : Syntax) : TacticM (TacticM Info) := do
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ open Meta
|
|||
def mkConvGoalFor (lhs : Expr) : MetaM (Expr × Expr) := do
|
||||
let lhsType ← inferType lhs
|
||||
let rhs ← mkFreshExprMVar lhsType
|
||||
let targetNew ← mkEq lhs rhs
|
||||
let targetNew := mkLHSGoal (← mkEq lhs rhs)
|
||||
let newGoal ← mkFreshExprSyntheticOpaqueMVar targetNew
|
||||
return (rhs, newGoal)
|
||||
|
||||
|
|
@ -23,7 +23,7 @@ def convert (lhs : Expr) (conv : TacticM Unit) : TacticM (Expr × Expr) := do
|
|||
let savedGoals ← getGoals
|
||||
try
|
||||
setGoals [newGoal.mvarId!]
|
||||
withReader (fun ctx => { ctx with inConv := true }) conv
|
||||
conv
|
||||
pruneSolvedGoals
|
||||
for mvarId in (← getGoals) do
|
||||
try
|
||||
|
|
@ -52,7 +52,7 @@ def getRhs : TacticM Expr :=
|
|||
/-- `⊢ lhs = rhs` ~~> `⊢ lhs' = rhs` using `h : lhs = lhs'`. -/
|
||||
def updateLhs (lhs' : Expr) (h : Expr) : TacticM Unit := do
|
||||
let rhs ← getRhs
|
||||
let newGoal ← mkFreshExprSyntheticOpaqueMVar (← mkEq lhs' rhs)
|
||||
let newGoal ← mkFreshExprSyntheticOpaqueMVar (mkLHSGoal (← mkEq lhs' rhs))
|
||||
assignExprMVar (← getMainGoal) (← mkEqTrans h newGoal)
|
||||
replaceMainGoal [newGoal.mvarId!]
|
||||
|
||||
|
|
@ -60,7 +60,7 @@ def updateLhs (lhs' : Expr) (h : Expr) : TacticM Unit := do
|
|||
def changeLhs (lhs' : Expr) : TacticM Unit := do
|
||||
let rhs ← getRhs
|
||||
liftMetaTactic1 fun mvarId => do
|
||||
replaceTargetDefEq mvarId (← mkEq lhs' rhs)
|
||||
replaceTargetDefEq mvarId (mkLHSGoal (← mkEq lhs' rhs))
|
||||
|
||||
@[builtinTactic Lean.Parser.Tactic.Conv.skip] def evalSkip : Tactic := fun stx => do
|
||||
liftMetaTactic1 fun mvarId => do
|
||||
|
|
|
|||
|
|
@ -1038,6 +1038,22 @@ def annotation? (kind : Name) (e : Expr) : Option Expr :=
|
|||
| Expr.mdata d b _ => if d.size == 1 && d.getBool kind false then some b else none
|
||||
| _ => none
|
||||
|
||||
/--
|
||||
Annotate `e` with the LHS annotation. The delaborator displays
|
||||
expressions of the form `lhs = rhs` as `lhs` when they have this annotation.
|
||||
-/
|
||||
def mkLHSGoal (e : Expr) : Expr :=
|
||||
mkAnnotation `_lhsGoal e
|
||||
|
||||
def isLHSGoal? (e : Expr) : Option Expr :=
|
||||
match annotation? `_lhsGoal e with
|
||||
| none => none
|
||||
| some e =>
|
||||
if e.isAppOfArity `Eq 3 then
|
||||
some e.appFn!.appArg!
|
||||
else
|
||||
none
|
||||
|
||||
def mkFreshFVarId {m : Type → Type} [Monad m] [MonadNameGenerator m] : m FVarId :=
|
||||
mkFreshId
|
||||
|
||||
|
|
|
|||
|
|
@ -144,20 +144,7 @@ end ToHide
|
|||
private def addLine (fmt : Format) : Format :=
|
||||
if fmt.isNil then fmt else fmt ++ Format.line
|
||||
|
||||
/--
|
||||
Return the target type for the given goal.
|
||||
If `inConv == true` and target type is an equality, then return the left-hand-side only. -/
|
||||
def getGoalTarget (mvarDecl : MetavarDecl) (inConv : Bool) : MetaM Expr := do
|
||||
let target ← instantiateMVars mvarDecl.type
|
||||
if inConv then
|
||||
if let some (_, lhs, _) ← matchEq? target then
|
||||
instantiateMVars lhs
|
||||
else
|
||||
return target
|
||||
else
|
||||
return target
|
||||
|
||||
def ppGoal (mvarId : MVarId) (inConv := false) : MetaM Format := do
|
||||
def ppGoal (mvarId : MVarId) : MetaM Format := do
|
||||
match (← getMCtx).findDecl? mvarId with
|
||||
| none => pure "unknown goal"
|
||||
| some mvarDecl => do
|
||||
|
|
@ -214,7 +201,7 @@ def ppGoal (mvarId : MVarId) (inConv := false) : MetaM Format := do
|
|||
ppVars varNames prevType? fmt localDecl
|
||||
let fmt ← pushPending varNames type? fmt
|
||||
let fmt := addLine fmt
|
||||
let typeFmt ← ppExpr (← getGoalTarget mvarDecl inConv)
|
||||
let typeFmt ← ppExpr (← instantiateMVars mvarDecl.type)
|
||||
let fmt := fmt ++ "⊢ " ++ Format.nest indent typeFmt
|
||||
match mvarDecl.userName with
|
||||
| Name.anonymous => pure fmt
|
||||
|
|
|
|||
|
|
@ -446,6 +446,8 @@ def delabMData : Delab := do
|
|||
`(.($s)) -- We only include the inaccessible annotation when we are delaborating patterns
|
||||
else
|
||||
return s
|
||||
else if let some _ := isLHSGoal? (← getExpr) then
|
||||
withMDataExpr <| withAppFn <| withAppArg <| delab
|
||||
else
|
||||
withMDataOptions delab
|
||||
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ def getInteractiveGoals (p : Lsp.PlainGoalParams) : RequestM (RequestTask (Optio
|
|||
let goals ← List.join <$> rs.mapM fun { ctxInfo := ci, tacticInfo := ti, useAfter := useAfter } =>
|
||||
let ci := if useAfter then { ci with mctx := ti.mctxAfter } else { ci with mctx := ti.mctxBefore }
|
||||
let goals := if useAfter then ti.goalsAfter else ti.goalsBefore
|
||||
ci.runMetaM {} <| goals.mapM (fun g => Meta.withPPInaccessibleNames (Widget.goalToInteractive g ti.inConv))
|
||||
ci.runMetaM {} <| goals.mapM (fun g => Meta.withPPInaccessibleNames (Widget.goalToInteractive g))
|
||||
return some { goals := goals.toArray }
|
||||
|
||||
return none
|
||||
|
|
@ -182,7 +182,7 @@ partial def getInteractiveTermGoal (p : Lsp.PlainTermGoalParams)
|
|||
-- for binders, hide the last hypothesis (the binder itself)
|
||||
let lctx' := if ti.isBinder then i.lctx.pop else i.lctx
|
||||
let goal ← ci.runMetaM lctx' do
|
||||
Meta.withPPInaccessibleNames <| Widget.goalToInteractive (← Meta.mkFreshExprMVar ty).mvarId! (inConv := false)
|
||||
Meta.withPPInaccessibleNames <| Widget.goalToInteractive (← Meta.mkFreshExprMVar ty).mvarId!
|
||||
let range := if let some r := i.range? then r.toLspRange text else ⟨p.position, p.position⟩
|
||||
return some { goal with range }
|
||||
return none
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ structure InteractiveGoals where
|
|||
|
||||
open Meta in
|
||||
/-- A variant of `Meta.ppGoal` which preserves subexpression information for interactivity. -/
|
||||
def goalToInteractive (mvarId : MVarId) (inConv : Bool) : MetaM InteractiveGoal := do
|
||||
def goalToInteractive (mvarId : MVarId) : MetaM InteractiveGoal := do
|
||||
let some mvarDecl ← (← getMCtx).findDecl? mvarId
|
||||
| throwError "unknown goal {mvarId}"
|
||||
let ppAuxDecls := pp.auxDecls.get (← getOptions)
|
||||
|
|
@ -118,7 +118,7 @@ def goalToInteractive (mvarId : MVarId) (inConv : Bool) : MetaM InteractiveGoal
|
|||
else
|
||||
ppVars varNames prevType? hyps localDecl
|
||||
let hyps ← pushPending varNames type? hyps
|
||||
let goalTp ← getGoalTarget mvarDecl inConv
|
||||
let goalTp ← instantiateMVars mvarDecl.type
|
||||
let goalFmt ← exprToInteractive goalTp
|
||||
let userName? := match mvarDecl.userName with
|
||||
| Name.anonymous => none
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue