feat: save syntax around recursive applications
Motivation: better error messages at structural and well-founded recursion.
This commit is contained in:
parent
e38fab1b4e
commit
2d4d5ae96f
4 changed files with 55 additions and 3 deletions
|
|
@ -40,3 +40,4 @@ import Lean.Elab.Notation
|
|||
import Lean.Elab.Mixfix
|
||||
import Lean.Elab.MacroRules
|
||||
import Lean.Elab.BuiltinCommand
|
||||
import Lean.Elab.RecAppSyntax
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import Lean.Elab.Term
|
|||
import Lean.Elab.Binders
|
||||
import Lean.Elab.SyntheticMVars
|
||||
import Lean.Elab.Arg
|
||||
import Lean.Elab.RecAppSyntax
|
||||
|
||||
namespace Lean.Elab.Term
|
||||
open Meta
|
||||
|
|
@ -913,7 +914,13 @@ private def elabAppAux (f : Syntax) (namedArgs : Array NamedArg) (args : Array A
|
|||
@[builtinTermElab app] def elabApp : TermElab := fun stx expectedType? =>
|
||||
withoutPostponingUniverseConstraints do
|
||||
let (f, namedArgs, args, ellipsis) ← expandApp stx
|
||||
elabAppAux f namedArgs args (ellipsis := ellipsis) expectedType?
|
||||
let result ← elabAppAux f namedArgs args (ellipsis := ellipsis) expectedType?
|
||||
let resultFn := result.getAppFn
|
||||
if resultFn.isFVar then
|
||||
let localDecl ← getLocalDecl resultFn.fvarId!
|
||||
if localDecl.isAuxDecl then
|
||||
return mkRecAppWithSyntax result stx
|
||||
return result
|
||||
|
||||
private def elabAtom : TermElab := fun stx expectedType? =>
|
||||
elabAppAux stx #[] #[] (ellipsis := false) expectedType?
|
||||
|
|
|
|||
30
src/Lean/Elab/RecAppSyntax.lean
Normal file
30
src/Lean/Elab/RecAppSyntax.lean
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/-
|
||||
Copyright (c) 2021 Microsoft Corporation. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
Authors: Leonardo de Moura
|
||||
-/
|
||||
import Lean.Expr
|
||||
|
||||
namespace Lean
|
||||
|
||||
private def recAppKey := `_recApp
|
||||
|
||||
/--
|
||||
We store the syntax at recursive applications to be able to generate better error messages
|
||||
when performing well-founded and structural recursion.
|
||||
-/
|
||||
def mkRecAppWithSyntax (e : Expr) (stx : Syntax) : Expr :=
|
||||
mkMData (KVMap.empty.insert recAppKey (DataValue.ofSyntax stx)) e
|
||||
|
||||
/--
|
||||
Retrieve (if available) the syntax object attached to a recursive application.
|
||||
-/
|
||||
def getRecAppSyntax? (e : Expr) : Option Syntax :=
|
||||
match e with
|
||||
| Expr.mdata d b _ =>
|
||||
match d.find recAppKey with
|
||||
| some (DataValue.ofSyntax stx) => some stx
|
||||
| _ => none
|
||||
| _ => none
|
||||
|
||||
end Lean
|
||||
|
|
@ -1,7 +1,14 @@
|
|||
{"textDocument": {"uri": "file://863.lean"},
|
||||
"position": {"line": 3, "character": 12}}
|
||||
{"items":
|
||||
[{"label": "getReducibilityStatus",
|
||||
[{"label": "getRecAppSyntax?",
|
||||
"kind": 3,
|
||||
"documentation":
|
||||
{"value":
|
||||
"Retrieve (if available) the syntax object attached to a recursive application.\n",
|
||||
"kind": "markdown"},
|
||||
"detail": "Expr → Option Syntax"},
|
||||
{"label": "getReducibilityStatus",
|
||||
"kind": 3,
|
||||
"detail":
|
||||
"[inst : Monad m] → [inst : MonadEnv m] → Name → m ReducibilityStatus"},
|
||||
|
|
@ -19,7 +26,14 @@
|
|||
{"textDocument": {"uri": "file://863.lean"},
|
||||
"position": {"line": 7, "character": 12}}
|
||||
{"items":
|
||||
[{"label": "getReducibilityStatus",
|
||||
[{"label": "getRecAppSyntax?",
|
||||
"kind": 3,
|
||||
"documentation":
|
||||
{"value":
|
||||
"Retrieve (if available) the syntax object attached to a recursive application.\n",
|
||||
"kind": "markdown"},
|
||||
"detail": "Expr → Option Syntax"},
|
||||
{"label": "getReducibilityStatus",
|
||||
"kind": 3,
|
||||
"detail":
|
||||
"[inst : Monad m] → [inst : MonadEnv m] → Name → m ReducibilityStatus"},
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue