feat: add TermInfo for LVal

@Vtec234 Added the missing info.
Given
```lean
def f3 (s : Nat × Array (Array Nat)) : Array Nat :=
  s.2[1].push s.1
```
We produce the following `InfoTree` for the body (originally at line 30)
```
Array.push (Array.getOp s.snd 1) s.fst : Array Nat @ ⟨30, 2⟩-⟨30, 17⟩
  s : Nat × Array (Array Nat) @ ⟨30, 2⟩-⟨30, 3⟩
  Prod.snd : {α β : Type} → α × β → β @ ⟨30, 4⟩-⟨30, 5⟩
  Array.getOp : {α : Type} → [inst : Inhabited α] → Array α → Nat → α @ ⟨30, 5⟩-⟨30, 6⟩
  1 : Nat @ ⟨30, 6⟩-⟨30, 7⟩
  Array.push : {α : Type} → Array α → α → Array α @ ⟨30, 9⟩-⟨30, 13⟩
  s.fst : Nat @ ⟨30, 14⟩-⟨30, 17⟩
    s : Nat × Array (Array Nat) @ ⟨30, 14⟩-⟨30, 15⟩
    Prod.fst : {α β : Type} → α × β → α @ ⟨30, 16⟩-⟨30, 17⟩
```
This commit is contained in:
Leonardo de Moura 2021-01-14 12:15:28 -08:00
parent fb52ec8ef5
commit 25c9727a92
5 changed files with 32 additions and 8 deletions

View file

@ -690,10 +690,12 @@ private def elabAppLValsAux (namedArgs : Array NamedArg) (args : Array Arg) (exp
match lvalRes with
| LValResolution.projIdx structName idx =>
let f := mkProj structName idx f
addTermInfo lval.getRef f
loop f lvals
| LValResolution.projFn baseStructName structName fieldName =>
let f ← mkBaseProjections baseStructName structName f
let projFn ← mkConst (baseStructName ++ fieldName)
addTermInfo lval.getRef projFn
if lvals.isEmpty then
let namedArgs ← addNamedArg namedArgs { name := `self, val := Arg.expr f }
elabAppArgs projFn namedArgs args expectedType? explicit ellipsis
@ -703,6 +705,7 @@ private def elabAppLValsAux (namedArgs : Array NamedArg) (args : Array Arg) (exp
| LValResolution.const baseStructName structName constName =>
let f ← if baseStructName != structName then mkBaseProjections baseStructName structName f else pure f
let projFn ← mkConst constName
addTermInfo lval.getRef projFn
if lvals.isEmpty then
let projFnType ← inferType projFn
let (args, namedArgs) ← addLValArg baseStructName constName f args namedArgs projFnType
@ -711,6 +714,7 @@ private def elabAppLValsAux (namedArgs : Array NamedArg) (args : Array Arg) (exp
let f ← elabAppArgs projFn #[] #[Arg.expr f] (expectedType? := none) (explicit := false) (ellipsis := false)
loop f lvals
| LValResolution.localRec baseName fullName fvar =>
addTermInfo lval.getRef fvar
if lvals.isEmpty then
let fvarType ← inferType fvar
let (args, namedArgs) ← addLValArg baseName fullName f args namedArgs fvarType
@ -720,6 +724,7 @@ private def elabAppLValsAux (namedArgs : Array NamedArg) (args : Array Arg) (exp
loop f lvals
| LValResolution.getOp fullName idx =>
let getOpFn ← mkConst fullName
addTermInfo lval.getRef getOpFn
if lvals.isEmpty then
let namedArgs ← addNamedArg namedArgs { name := `self, val := Arg.expr f }
let namedArgs ← addNamedArg namedArgs { name := `idx, val := Arg.stx idx }
@ -770,6 +775,8 @@ private partial def elabAppFnId (fIdent : Syntax) (fExplicitUnivs : List Level)
-- Set `errToSorry` to `false` if `funLVals` > 1. See comment above about the interaction between `errToSorry` and `observing`.
withReader (fun ctx => { ctx with errToSorry := funLVals.length == 1 && ctx.errToSorry }) do
funLVals.foldlM (init := acc) fun acc ⟨f, fields⟩ => do
unless lvals.isEmpty && args.isEmpty && namedArgs.isEmpty do
addTermInfo fIdent f
let lvals' := fields.map (LVal.fieldName fIdent)
let s ← observing do
let e ← elabAppLVals f (lvals' ++ lvals) namedArgs args expectedType? explicit ellipsis
@ -784,17 +791,17 @@ private partial def elabAppFn (f : Syntax) (lvals : List LVal) (namedArgs : Arra
withReader (fun ctx => { ctx with errToSorry := false }) do
f.getArgs.foldlM (fun acc f => elabAppFn f lvals namedArgs args expectedType? explicit ellipsis true acc) acc
else match f with
| `($(e).$idx:fieldIdx) =>
let idx := idx.isFieldIdx?.get!
elabAppFn e (LVal.fieldIdx f idx :: lvals) namedArgs args expectedType? explicit ellipsis overloaded acc
| `($(e).$idxStx:fieldIdx) =>
let idx := idxStx.isFieldIdx?.get!
elabAppFn e (LVal.fieldIdx idxStx idx :: lvals) namedArgs args expectedType? explicit ellipsis overloaded acc
| `($e |>. $field) => do
let f ← `($(e).$field)
elabAppFn f lvals namedArgs args expectedType? explicit ellipsis overloaded acc
| `($(e).$field:ident) =>
let newLVals := field.getId.eraseMacroScopes.components.map (fun n => LVal.fieldName f (toString n))
let newLVals := field.getId.eraseMacroScopes.components.map (fun n => LVal.fieldName field (toString n))
elabAppFn e (newLVals ++ lvals) namedArgs args expectedType? explicit ellipsis overloaded acc
| `($e[$idx]) =>
elabAppFn e (LVal.getOp f idx :: lvals) namedArgs args expectedType? explicit ellipsis overloaded acc
| `($e[%$bracket $idx]) =>
elabAppFn e (LVal.getOp bracket idx :: lvals) namedArgs args expectedType? explicit ellipsis overloaded acc
| `($id:ident@$t:term) =>
throwError "unexpected occurrence of named pattern"
| `($id:ident) => do

View file

@ -287,7 +287,9 @@ def liftTermElabM {α} (declName? : Option Name) (x : TermElabM α) : CommandEla
let (((ea, termS), metaS), coreS) ← liftEIO x
let infoTrees := termS.infoState.trees.map fun tree =>
let tree := tree.substitute termS.infoState.assignment
InfoTree.context { env := coreS.env, mctx := metaS.mctx, currNamespace := scope.currNamespace, openDecls := scope.openDecls, options := scope.opts } tree
InfoTree.context {
env := coreS.env, fileMap := ctx.fileMap, mctx := metaS.mctx, currNamespace := scope.currNamespace, openDecls := scope.openDecls, options := scope.opts
} tree
modify fun s => { s with
env := coreS.env
messages := addTraceAsMessages ctx (s.messages ++ termS.messages) coreS.traceState

View file

@ -20,6 +20,7 @@ open Std (PersistentArray PersistentArray.empty PersistentHashMap)
assignments are stored at `mctx`. -/
structure ContextInfo where
env : Environment
fileMap : FileMap
mctx : MetavarContext := {}
options : Options := {}
currNamespace : Name := Name.anonymous
@ -101,7 +102,9 @@ def ContextInfo.ppSyntax (info : ContextInfo) (lctx : LocalContext) (stx : Synta
def TermInfo.format (cinfo : ContextInfo) (info : TermInfo) : IO Format := do
cinfo.runMetaM info.lctx do
return f!"{← Meta.ppExpr info.expr} : {← Meta.ppExpr (← Meta.inferType info.expr)}"
let pos := info.stx.getPos.getD 0
let endPos := info.stx.getTailPos.getD pos
return f!"{← Meta.ppExpr info.expr} : {← Meta.ppExpr (← Meta.inferType info.expr)} @ {cinfo.fileMap.toPosition pos}-{cinfo.fileMap.toPosition endPos}"
def ContextInfo.ppGoals (cinfo : ContextInfo) (goals : List MVarId) : IO Format :=
if goals.isEmpty then

View file

@ -279,6 +279,11 @@ inductive LVal where
| fieldName (ref : Syntax) (name : String)
| getOp (ref : Syntax) (idx : Syntax)
def LVal.getRef : LVal → Syntax
| LVal.fieldIdx ref _ => ref
| LVal.fieldName ref _ => ref
| LVal.getOp ref _ => ref
instance : ToString LVal where
toString
| LVal.fieldIdx _ i => toString i
@ -987,6 +992,10 @@ private partial def elabTermAux (expectedType? : Option Expr) (catchExPostpone :
| some expectedType => elabImplicitLambda stx catchExPostpone expectedType #[]
| none => elabUsingElabFns stx expectedType? catchExPostpone
def addTermInfo (stx : Syntax) (e : Expr) : TermElabM Unit := do
if (← getInfoState).enabled then
pushInfoTree <| InfoTree.node (children := {}) <| Info.ofTermInfo { lctx := (← getLCtx), expr := e, stx := stx }
def mkTermInfo (stx : Syntax) (e : Expr) : TermElabM (Sum Info MVarId) := do
let isHole? : TermElabM (Option MVarId) := do
match e with

View file

@ -26,4 +26,7 @@ def f2 : (x y : Nat) → (b : Bool) → Nat :=
let z1 := z + w
z + z1
def f3 (s : Nat × Array (Array Nat)) : Array Nat :=
s.2[1].push s.1
showInfoTrees!