feat: extend valid set of valid auto bound names

@Kha The motivation was Andrew's example :)
Users often use `u₁`, `u1`, `u₂`, ... to name universe variables.
This commit is contained in:
Leonardo de Moura 2020-12-19 12:36:19 -08:00
parent 498dae8fab
commit bbcd2247f2
5 changed files with 47 additions and 23 deletions

View file

@ -21,8 +21,11 @@ def isLetterLike (c : Char) : Bool :=
(0x2100 ≤ c.val && c.val ≤ 0x214f) || -- Letter like block
(0x1d49c ≤ c.val && c.val ≤ 0x1d59f) -- Latin letters, Script, Double-struck, Fractur
def isNumericSubscript (c : Char) : Bool :=
0x2080 ≤ c.val && c.val ≤ 0x2089
def isSubScriptAlnum (c : Char) : Bool :=
(0x2080 ≤ c.val && c.val ≤ 0x2089) || -- numeric subscripts
isNumericSubscript c ||
(0x2090 ≤ c.val && c.val ≤ 0x209c) ||
(0x1d62 ≤ c.val && c.val ≤ 0x1d6a)

View file

@ -0,0 +1,35 @@
/-
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.Data.Options
/- Basic support for auto bound implicit local names -/
namespace Lean.Elab
builtin_initialize
registerOption `autoBoundImplicitLocal {
defValue := true
group := ""
descr := "Unbound local variables in declaration headers become implicit arguments if they are a lower case or greek letter followed by numeric digits. For example, `def f (x : Vector α n) : Vector α n :=` automatically introduces the implicit variables {α n}"
}
def getAutoBoundImplicitLocalOption (opts : Options) : Bool :=
opts.get `autoBoundImplicitLocal true
private def allNumeral (s : Substring) : Bool :=
s.all fun c => c.isDigit || isNumericSubscript c
def isValidAutoBoundImplicitName (n : Name) : Bool :=
match n.eraseMacroScopes with
| Name.str Name.anonymous s _ => s.length > 0 && (isGreek s[0] || s[0].isLower) && allNumeral (s.toSubstring.drop 1)
| _ => false
def isValidAutoBoundLevelName (n : Name) : Bool :=
match n.eraseMacroScopes with
| Name.str Name.anonymous s _ => s.length > 0 && s[0].isLower && allNumeral (s.toSubstring.drop 1)
| _ => false
end Lean.Elab

View file

@ -6,6 +6,7 @@ Authors: Leonardo de Moura
import Lean.Meta.LevelDefEq
import Lean.Elab.Exception
import Lean.Elab.Log
import Lean.Elab.AutoBound
namespace Lean.Elab.Level
@ -33,17 +34,11 @@ instance : MonadNameGenerator LevelElabM where
setNGen ngen := modify fun s => { s with ngen := ngen }
def mkFreshLevelMVar : LevelElabM Level := do
let mvarId ← mkFreshId
modify fun s => { s with mctx := s.mctx.addLevelMVarDecl mvarId }
return mkLevelMVar mvarId
private def isValidAutoBoundLevelName (n : Name) : Bool :=
match n.eraseMacroScopes with
| Name.str Name.anonymous s _ => s.length == 1 && s[0].isLower
| _ => false
partial def elabLevel (stx : Syntax) : LevelElabM Level := withRef stx do
let kind := stx.getKind
if kind == `Lean.Parser.Level.paren then

View file

@ -16,6 +16,7 @@ import Lean.Util.RecDepth
import Lean.Elab.Log
import Lean.Elab.Level
import Lean.Elab.Attributes
import Lean.Elab.AutoBound
namespace Lean.Elab.Term
/-
@ -297,16 +298,6 @@ def withLevelNames {α} (levelNames : List Name) (x : TermElabM α) : TermElabM
def withoutErrToSorry {α} (x : TermElabM α) : TermElabM α :=
withReader (fun ctx => { ctx with errToSorry := false }) x
builtin_initialize
registerOption `autoBoundImplicitLocal {
defValue := true
group := ""
descr := "Unbound local variables in declaration headers become implicit arguments if they are a lower case or greek letter. For example, `def f (x : Vector α n) : Vector α n :=` automatically introduces the implicit variables {α n}"
}
private def getAutoBoundImplicitLocalOption (opts : Options) : Bool :=
opts.get `autoBoundImplicitLocal true
/-- Execute `x` with `autoBoundImplicit = (options.get `autoBoundImplicitLocal) && flag` -/
def withAutoBoundImplicitLocal {α} (x : TermElabM α) (flag := true) : TermElabM α := do
let flag := getAutoBoundImplicitLocalOption (← getOptions) && flag
@ -1217,11 +1208,6 @@ private def mkConsts (candidates : List (Name × List String)) (explicitLevels :
let const ← mkConst constName explicitLevels
pure $ (const, projs) :: result
def isValidAutoBoundImplicitName (n : Name) : Bool :=
match n.eraseMacroScopes with
| Name.str Name.anonymous s _ => s.length == 1 && (isGreek s[0] || s[0].isLower)
| _ => false
def resolveName (n : Name) (preresolved : List (Name × List String)) (explicitLevels : List Level) : TermElabM (List (Expr × List String)) := do
match (← resolveLocalName n) with
| some (e, projs) =>

View file

@ -16,7 +16,7 @@ def mkVec : Vec α 0 := ⟨ #[], rfl ⟩
def Vec.map (xs : Vec α n) (f : α → β) : Vec β n :=
⟨ xs.val.map f, sorry ⟩
/- unbound implicit locals must be greek or lower case letters -/
/- unbound implicit locals must be greek or lower case letters followed by numerical digits -/
def Vec.map2 (xs : Vec α size /- error: unknown identifier size -/) (f : α → β) : Vec β n :=
⟨ xs.val.map f, sorry ⟩
@ -65,3 +65,8 @@ def findSomeRev? (as : Array α) (f : α → Option β) : Option β :=
Id.run <| findSomeRevM? as f
end Ex1
def apply {α : Type u₁} {β : α → Type u₂} (f : (a : α) → β a) (a : α) : β a :=
f a
def pair (a : α₁) := (a, a)