fix: local syntax should create private definitions
This commit is contained in:
parent
8d34dfe914
commit
d4a5a2c632
14 changed files with 113 additions and 92 deletions
|
|
@ -20,11 +20,11 @@ Declares an auxiliary definition with an automatically generated name.
|
|||
For example, `aux_def foo : Nat := 42` creates a definition
|
||||
with an internal, unused name based on the suggestion `foo`.
|
||||
-/
|
||||
scoped syntax (name := aux_def) docComment ? attributes ? "aux_def" ident+ ":" term ":=" term : command
|
||||
scoped syntax (name := aux_def) docComment ? attributes ? visibility "aux_def" ident+ ":" term ":=" term : command
|
||||
|
||||
@[builtin_command_elab «aux_def»]
|
||||
def elabAuxDef : CommandElab
|
||||
| `($[$doc?:docComment]? $[$attrs?:attributes]? aux_def $suggestion* : $ty := $body) => do
|
||||
| `($[$doc?:docComment]? $[$attrs?:attributes]? $vis:visibility aux_def $suggestion* : $ty := $body) => do
|
||||
let id := suggestion.map (·.getId.eraseMacroScopes) |>.foldl (· ++ ·) Name.anonymous
|
||||
let id := `_aux ++ (← getMainModule) ++ `_ ++ id
|
||||
let id := String.intercalate "_" <| id.components.map (·.toString (escape := false))
|
||||
|
|
@ -36,6 +36,6 @@ def elabAuxDef : CommandElab
|
|||
let (id, _) := DeclNameGenerator.ofPrefix ns |>.mkUniqueName env («infix» := Name.mkSimple id)
|
||||
let id := id.replacePrefix ns Name.anonymous -- TODO: replace with def _root_.id
|
||||
elabCommand <|
|
||||
← `($[$doc?:docComment]? $[$attrs?:attributes]?
|
||||
← `($[$doc?:docComment]? $[$attrs?:attributes]? $vis:visibility
|
||||
meta def $(mkIdentFrom (mkNullNode suggestion) id (canonical := true)):ident : $ty := $body)
|
||||
| _ => throwUnsupportedSyntax
|
||||
|
|
|
|||
|
|
@ -21,18 +21,14 @@ namespace Lean.Elab.Command
|
|||
$[(name := $name?)]? $[(priority := $prio?)]? $x $args:macroArg* => $rhs) => do
|
||||
let prio ← liftMacroM do evalOptPrio prio?
|
||||
let (stxParts, patArgs) := (← args.mapM expandMacroArg).unzip
|
||||
let name ← match name? with
|
||||
| some name => pure name.getId
|
||||
| none => liftMacroM do mkNameFromParserSyntax `binderTerm (mkNullNode stxParts)
|
||||
let nameTk := name?.getD (mkIdentFrom tk name)
|
||||
let kind ← elabSyntax (← `($[$doc?:docComment]? $[@[$attrs?,*]]? $attrKind:attrKind syntax%$tk
|
||||
$[(name := $name?)]? (priority := $(quote prio)) $[$stxParts]* : binderPred))
|
||||
/- The command `syntax [<kind>] ...` adds the current namespace to the syntax node kind.
|
||||
So, we must include current namespace when we create a pattern for the following
|
||||
`macro_rules` commands. -/
|
||||
let pat : TSyntax `binderPred := ⟨(mkNode ((← getCurrNamespace) ++ name) patArgs).1⟩
|
||||
let pat : TSyntax `binderPred := ⟨(mkNode kind patArgs).1⟩
|
||||
elabCommand <|<-
|
||||
`($[$doc?:docComment]? $[@[$attrs?,*]]? $attrKind:attrKind syntax%$tk
|
||||
(name := $nameTk) (priority := $(quote prio)) $[$stxParts]* : binderPred
|
||||
$[$doc?:docComment]? macro_rules%$tk
|
||||
`($[$doc?:docComment]? macro_rules%$tk
|
||||
| `(satisfies_binder_pred% $$($x):term $pat:binderPred) => $rhs)
|
||||
| _ => throwUnsupportedSyntax
|
||||
|
||||
|
|
|
|||
|
|
@ -50,25 +50,26 @@ def elabElabRulesAux (doc? : Option (TSyntax ``docComment))
|
|||
pure <| match attrs? with
|
||||
| some attrs => attrs.getElems.push attr
|
||||
| none => #[attr]
|
||||
let vis := Parser.Command.visibility.ofAttrKind attrKind
|
||||
if let some expId := expty? then
|
||||
if catName == `term then
|
||||
`($[$doc?:docComment]? @[$(← mkAttrs `term_elab),*]
|
||||
`($[$doc?:docComment]? @[$(← mkAttrs `term_elab),*] $vis:visibility
|
||||
aux_def elabRules $(mkIdent k) : Lean.Elab.Term.TermElab :=
|
||||
fun stx expectedType? => Lean.Elab.Term.withExpectedType expectedType? fun $expId => match stx with
|
||||
$alts:matchAlt* | _ => no_error_if_unused% throwUnsupportedSyntax)
|
||||
else
|
||||
throwErrorAt expId "syntax category '{catName}' does not support expected type specification"
|
||||
else if catName == `term then
|
||||
`($[$doc?:docComment]? @[$(← mkAttrs `term_elab),*]
|
||||
`($[$doc?:docComment]? @[$(← mkAttrs `term_elab),*] $vis:visibility
|
||||
aux_def elabRules $(mkIdent k) : Lean.Elab.Term.TermElab :=
|
||||
fun stx _ => match stx with
|
||||
$alts:matchAlt* | _ => no_error_if_unused% throwUnsupportedSyntax)
|
||||
else if catName == `command then
|
||||
`($[$doc?:docComment]? @[$(← mkAttrs `command_elab),*]
|
||||
`($[$doc?:docComment]? @[$(← mkAttrs `command_elab),*] $vis:visibility
|
||||
aux_def elabRules $(mkIdent k) : Lean.Elab.Command.CommandElab :=
|
||||
fun $alts:matchAlt* | _ => no_error_if_unused% throwUnsupportedSyntax)
|
||||
else if catName == `tactic || catName == `conv then
|
||||
`($[$doc?:docComment]? @[$(← mkAttrs `tactic),*]
|
||||
`($[$doc?:docComment]? @[$(← mkAttrs `tactic),*] $vis:visibility
|
||||
aux_def elabRules $(mkIdent k) : Lean.Elab.Tactic.Tactic :=
|
||||
fun $alts:matchAlt* | _ => no_error_if_unused% throwUnsupportedSyntax)
|
||||
else
|
||||
|
|
@ -92,15 +93,11 @@ def elabElab : CommandElab
|
|||
$cat $[<= $expectedType?]? => $rhs) => do
|
||||
let prio ← liftMacroM <| evalOptPrio prio?
|
||||
let (stxParts, patArgs) := (← args.mapM expandMacroArg).unzip
|
||||
-- name
|
||||
let name ← match name? with
|
||||
| some name => pure name.getId
|
||||
| none => addMacroScopeIfLocal (← liftMacroM <| mkNameFromParserSyntax cat.getId (mkNullNode stxParts)) attrKind
|
||||
let nameId := name?.getD (mkIdentFrom tk name (canonical := true))
|
||||
let pat := ⟨mkNode ((← getCurrNamespace) ++ name) patArgs⟩
|
||||
elabCommand <|← `(
|
||||
let kind ← elabSyntax <|← `(
|
||||
$[$doc?:docComment]? $[@[$attrs?,*]]? $attrKind:attrKind
|
||||
syntax%$tk$[:$prec?]? (name := $nameId) (priority := $(quote prio):num) $[$stxParts]* : $cat
|
||||
syntax%$tk$[:$prec?]? $[(name := $name?)]? (priority := $(quote prio):num) $[$stxParts]* : $cat)
|
||||
let pat := ⟨mkNode kind patArgs⟩
|
||||
elabCommand <|← `(
|
||||
$[$doc?:docComment]? elab_rules : $cat $[<= $expectedType?]? | `($pat) => $rhs)
|
||||
| _ => throwUnsupportedSyntax
|
||||
|
||||
|
|
|
|||
|
|
@ -23,29 +23,28 @@ open Lean.Parser.Command
|
|||
withRef (mkNullNode #[tk, rhs]) do
|
||||
let prio ← liftMacroM <| evalOptPrio prio?
|
||||
let (stxParts, patArgs) := (← args.mapM expandMacroArg).unzip
|
||||
-- name
|
||||
let name ← match name? with
|
||||
| some name => pure name.getId
|
||||
| none => addMacroScopeIfLocal (← liftMacroM <| mkNameFromParserSyntax cat.getId (mkNullNode stxParts)) attrKind
|
||||
/- The command `syntax [<kind>] ...` adds the current namespace to the syntax node kind.
|
||||
So, we must include current namespace when we create a pattern for the following `macro_rules` commands. -/
|
||||
let pat := ⟨mkNode ((← getCurrNamespace) ++ name) patArgs⟩
|
||||
let stxCmd ← `($[$doc?:docComment]? $[@[$attrs?,*]]? $attrKind:attrKind
|
||||
let kind ← elabSyntax (← `($[$doc?:docComment]? $[@[$attrs?,*]]? $attrKind:attrKind
|
||||
syntax$[:$prec?]?
|
||||
(name := $(name?.getD (mkIdentFrom tk name (canonical := true))))
|
||||
$[(name := $name?)]?
|
||||
(priority := $(quote prio):num)
|
||||
$[$stxParts]* : $cat)
|
||||
$[$stxParts]* : $cat))
|
||||
let pat := ⟨mkNode kind patArgs⟩
|
||||
let rhs := rhs.raw
|
||||
-- Elide `scoped` for `macro_rules`; this allows for using scoped macros in unscoped macros
|
||||
-- for back-compat and unlike with `local`, there would be no benefit to enforcing `scoped`.
|
||||
let mut rulesKind := attrKind
|
||||
if rulesKind matches `(attrKind| scoped) then
|
||||
rulesKind ← `(attrKind| )
|
||||
let macroRulesCmd ← if rhs.getArgs.size == 1 then
|
||||
-- `rhs` is a `term`
|
||||
let rhs := ⟨rhs[0]⟩
|
||||
`($[$doc?:docComment]? macro_rules | `($pat) => Functor.map (@TSyntax.raw $(quote cat.getId.eraseMacroScopes)) $rhs)
|
||||
`($[$doc?:docComment]? $rulesKind:attrKind macro_rules | `($pat) => Functor.map (@TSyntax.raw $(quote cat.getId.eraseMacroScopes)) $rhs)
|
||||
else
|
||||
-- TODO(gabriel): remove after bootstrap
|
||||
-- `rhs` is of the form `` `( $body ) ``
|
||||
let rhsBody := ⟨rhs[1]⟩
|
||||
`($[$doc?:docComment]? macro_rules | `($pat) => `($rhsBody))
|
||||
elabCommand <| mkNullNode #[stxCmd, macroRulesCmd]
|
||||
`($[$doc?:docComment]? $rulesKind:attrKind macro_rules | `($pat) => `($rhsBody))
|
||||
elabCommand macroRulesCmd
|
||||
| _ => throwUnsupportedSyntax
|
||||
|
||||
end Lean.Elab.Command
|
||||
|
|
|
|||
|
|
@ -47,7 +47,8 @@ def elabMacroRulesAux (doc? : Option (TSyntax ``docComment))
|
|||
let attrs := match attrs? with
|
||||
| some attrs => attrs.getElems.push attr
|
||||
| none => #[attr]
|
||||
`($[$doc?:docComment]? @[$attrs,*]
|
||||
let vis := Parser.Command.visibility.ofAttrKind attrKind
|
||||
`($[$doc?:docComment]? @[$attrs,*] $vis:visibility
|
||||
aux_def macroRules $(mkIdentFrom tk k (canonical := true)) : Macro :=
|
||||
fun $alts:matchAlt* | _ => no_error_if_unused% throw Lean.Macro.Exception.unsupportedSyntax)
|
||||
|
||||
|
|
@ -64,9 +65,11 @@ def elabMacroRulesAux (doc? : Option (TSyntax ``docComment))
|
|||
let attrs := match attrs? with
|
||||
| some attrs => attrs.getElems.push attr
|
||||
| none => #[attr]
|
||||
`($[$doc?:docComment]? @[$attrs,*]
|
||||
let vis := Parser.Command.visibility.ofAttrKind attrKind
|
||||
`($[$doc?:docComment]? @[$attrs,*] $vis:visibility
|
||||
aux_def $(mkIdentFrom tk kind.getId (canonical := true)) $kind : Macro := fun $x:ident => $rhs)
|
||||
| `($[$doc?:docComment]? $[@[$attrs?,*]]? $attrKind:attrKind macro_rules%$tk (kind := $kind) $alts:matchAlt*) =>
|
||||
withExporting (isExporting := !attrKind matches `(attrKind| local)) do
|
||||
withRef (mkNullNode #[tk, mkNullNode alts]) do
|
||||
elabMacroRulesAux doc? attrs? attrKind tk (← resolveSyntaxKind kind.getId) alts
|
||||
| _ => throwUnsupportedSyntax
|
||||
|
|
|
|||
|
|
@ -112,54 +112,39 @@ def mkUnexpander (attrKind : TSyntax ``attrKind) (pat qrhs : Term) : OptionT Mac
|
|||
-- The reference is attached to the syntactic representation of the called function itself, not the entire function application
|
||||
let lhs ← `($$f:ident)
|
||||
let lhs := Syntax.mkApp lhs (.mk args)
|
||||
`(@[$attrKind app_unexpander $(mkIdent c)]
|
||||
let vis := Parser.Command.visibility.ofAttrKind attrKind
|
||||
`(@[$attrKind app_unexpander $(mkIdent c)] $vis:visibility
|
||||
aux_def unexpand $(mkIdent c) : Lean.PrettyPrinter.Unexpander := fun
|
||||
| `($lhs) => withRef f `($pat)
|
||||
| _ => throw ())
|
||||
|
||||
private def expandNotationAux (ref : Syntax) (currNamespace : Name)
|
||||
(doc? : Option (TSyntax ``docComment))
|
||||
(attrs? : Option (TSepArray ``attrInstance ","))
|
||||
(attrKind : TSyntax ``attrKind)
|
||||
(prec? : Option Prec) (name? : Option Ident) (prio? : Option Prio)
|
||||
(items : Array (TSyntax ``notationItem)) (rhs : Term) : MacroM Syntax := do
|
||||
let prio ← evalOptPrio prio?
|
||||
-- build parser
|
||||
let syntaxParts ← items.mapM expandNotationItemIntoSyntaxItem
|
||||
let cat := mkIdentFrom ref `term
|
||||
let name ←
|
||||
match name? with
|
||||
| some name => pure name.getId
|
||||
| none => addMacroScopeIfLocal (← mkNameFromParserSyntax `term (mkNullNode syntaxParts)) attrKind
|
||||
-- build macro rules
|
||||
let vars := items.filter fun item => item.raw.getKind == ``identPrec
|
||||
let vars := vars.map fun var => var.raw[0]
|
||||
let qrhs := ⟨antiquote vars rhs⟩
|
||||
let attrs? := addInheritDocDefault rhs attrs?
|
||||
let patArgs ← items.mapM expandNotationItemIntoPattern
|
||||
/- The command `syntax [<kind>] ...` adds the current namespace to the syntax node kind.
|
||||
So, we must include current namespace when we create a pattern for the following `macro_rules` commands. -/
|
||||
let fullName := currNamespace ++ name
|
||||
let pat : Term := ⟨mkNode fullName patArgs⟩
|
||||
let stxDecl ← `($[$doc?:docComment]? $[@[$attrs?,*]]? $attrKind:attrKind
|
||||
syntax $[: $prec?]? (name := $(name?.getD (mkIdent name))) (priority := $(quote prio)) $[$syntaxParts]* : $cat)
|
||||
let macroDecl ← `(macro_rules | `($pat) => ``($qrhs))
|
||||
let macroDecls ←
|
||||
@[builtin_command_elab Lean.Parser.Command.notation] def elabNotation : CommandElab
|
||||
| ref@`($[$doc?:docComment]? $[@[$attrs?,*]]? $attrKind:attrKind
|
||||
notation $[: $prec?]? $[(name := $name?)]? $[(priority := $prio?)]? $items* => $rhs) => do
|
||||
let attrs? := addInheritDocDefault rhs attrs?
|
||||
let prio ← liftMacroM <| evalOptPrio prio?
|
||||
-- build parser
|
||||
let syntaxParts ← liftMacroM <| items.mapM expandNotationItemIntoSyntaxItem
|
||||
let cat := mkIdentFrom ref `term
|
||||
let kind ← elabSyntax (← `($[$doc?:docComment]? $[@[$attrs?,*]]? $attrKind:attrKind
|
||||
syntax $[: $prec?]? $[(name := $name?)]? (priority := $(quote prio)) $[$syntaxParts]* : $cat))
|
||||
-- build macro rules
|
||||
let vars := items.filter fun item => item.raw.getKind == ``identPrec
|
||||
let vars := vars.map fun var => var.raw[0]
|
||||
let qrhs := ⟨antiquote vars rhs⟩
|
||||
let patArgs ← liftMacroM <| items.mapM expandNotationItemIntoPattern
|
||||
let pat : Term := ⟨mkNode kind patArgs⟩
|
||||
let macroDecl ← `($attrKind:attrKind macro_rules | `($pat) => ``($qrhs))
|
||||
if isLocalAttrKind attrKind then
|
||||
-- Make sure the quotation pre-checker takes section variables into account for local notation.
|
||||
`(section set_option quotPrecheck.allowSectionVars true $macroDecl end)
|
||||
let opts ← getOptions
|
||||
let opts := Term.Quotation.quotPrecheck.allowSectionVars.set opts true
|
||||
withScope (fun sc => { sc with opts }) do
|
||||
elabCommand macroDecl
|
||||
else
|
||||
pure ⟨mkNullNode #[macroDecl]⟩
|
||||
match (← mkUnexpander attrKind pat qrhs |>.run) with
|
||||
| some delabDecl => return mkNullNode #[stxDecl, macroDecls, delabDecl]
|
||||
| none => return mkNullNode #[stxDecl, macroDecls]
|
||||
|
||||
@[builtin_macro Lean.Parser.Command.notation] def expandNotation : Macro
|
||||
| stx@`($[$doc?:docComment]? $[@[$attrs?,*]]? $attrKind:attrKind
|
||||
notation $[: $prec?]? $[(name := $name?)]? $[(priority := $prio?)]? $items* => $rhs) => do
|
||||
-- trigger scoped checks early and only once
|
||||
let _ ← toAttributeKind attrKind
|
||||
expandNotationAux stx (← Macro.getCurrNamespace) doc? attrs? attrKind prec? name? prio? items rhs
|
||||
| _ => Macro.throwUnsupported
|
||||
elabCommand macroDecl
|
||||
if let some delabDecl := (← liftMacroM <| mkUnexpander attrKind pat qrhs |>.run) then
|
||||
elabCommand delabDecl
|
||||
| _ => throwUnsupportedSyntax
|
||||
|
||||
end Lean.Elab.Command
|
||||
|
|
|
|||
|
|
@ -314,7 +314,7 @@ private def declareSyntaxCatQuotParser (catName : Name) : CommandElabM Unit := d
|
|||
```
|
||||
It generates the names `term_+_` and `term[_,]`
|
||||
-/
|
||||
partial def mkNameFromParserSyntax (catName : Name) (stx : Syntax) : MacroM Name := do
|
||||
private partial def mkNameFromParserSyntax (catName : Name) (stx : Syntax) : MacroM Name := do
|
||||
mkUnusedBaseName <| Name.mkSimple <| appendCatName <| visit stx ""
|
||||
where
|
||||
visit (stx : Syntax) (acc : String) : String :=
|
||||
|
|
@ -368,13 +368,14 @@ def isLocalAttrKind (attrKind : Syntax) : Bool :=
|
|||
/--
|
||||
Add macro scope to `name` if it does not already have them, and `attrKind` is `local`.
|
||||
-/
|
||||
def addMacroScopeIfLocal [MonadQuotation m] [Monad m] (name : Name) (attrKind : Syntax) : m Name := do
|
||||
private def addMacroScopeIfLocal [MonadQuotation m] [Monad m] (name : Name) (attrKind : Syntax) : m Name := do
|
||||
if isLocalAttrKind attrKind && !name.hasMacroScopes then
|
||||
MonadQuotation.addMacroScope name
|
||||
else
|
||||
return name
|
||||
|
||||
@[builtin_command_elab «syntax»] def elabSyntax : CommandElab := fun stx => do
|
||||
/-- Elaborates the given `syntax` command and returns the new node kind. -/
|
||||
def elabSyntax (stx : Syntax) : CommandElabM Name := do
|
||||
let `($[$doc?:docComment]? $[ @[ $attrInstances:attrInstance,* ] ]? $attrKind:attrKind
|
||||
syntax%$tk $[: $prec? ]? $[(name := $name?)]? $[(priority := $prio?)]? $[$ps:stx]* : $catStx) := stx
|
||||
| throwUnsupportedSyntax
|
||||
|
|
@ -390,24 +391,42 @@ def addMacroScopeIfLocal [MonadQuotation m] [Monad m] (name : Name) (attrKind :
|
|||
| none => pure precDefault
|
||||
let name ← match name? with
|
||||
| some name => pure name.getId
|
||||
| none => addMacroScopeIfLocal (← liftMacroM <| mkNameFromParserSyntax cat syntaxParser) attrKind
|
||||
| none =>
|
||||
let base ← liftMacroM <| mkNameFromParserSyntax cat syntaxParser
|
||||
let mut name := base
|
||||
let mut i := 1
|
||||
-- Avoid name conflicts, for which we have to check both public and private name
|
||||
while (←
|
||||
let fullName := (← getCurrNamespace) ++ name
|
||||
hasConst fullName <||>
|
||||
(withoutExporting <| hasConst (mkPrivateName (← getEnv) fullName))) do
|
||||
name := base.appendIndexAfter i
|
||||
i := i + 1
|
||||
pure name
|
||||
let prio ← liftMacroM <| evalOptPrio prio?
|
||||
let idRef := (name?.map (·.raw)).getD tk
|
||||
let stxNodeKind := (← getCurrNamespace) ++ name
|
||||
let mut stxNodeKind := (← getCurrNamespace) ++ name
|
||||
if attrKind matches `(attrKind| local) then
|
||||
stxNodeKind := mkPrivateName (← getEnv) stxNodeKind
|
||||
let catParserId := mkIdentFrom idRef (cat.appendAfter "_parser")
|
||||
let (val, lhsPrec?) ← runTermElabM fun _ => Term.toParserDescr syntaxParser cat
|
||||
let declName := name?.getD (mkIdentFrom idRef name (canonical := true))
|
||||
let attrInstance ← `(attrInstance| $attrKind:attrKind $catParserId:ident $(quote prio):num)
|
||||
let attrInstances := attrInstances.getD { elemsAndSeps := #[] }
|
||||
let attrInstances := attrInstances.push attrInstance
|
||||
let vis := Parser.Command.visibility.ofAttrKind attrKind
|
||||
let d ← if let some lhsPrec := lhsPrec? then
|
||||
`($[$doc?:docComment]? @[$attrInstances,*] meta def $declName:ident : Lean.TrailingParserDescr :=
|
||||
`($[$doc?:docComment]? @[$attrInstances,*] $vis:visibility meta def $declName:ident : Lean.TrailingParserDescr :=
|
||||
ParserDescr.trailingNode $(quote stxNodeKind) $(quote prec) $(quote lhsPrec) $val)
|
||||
else
|
||||
`($[$doc?:docComment]? @[$attrInstances,*] meta def $declName:ident : Lean.ParserDescr :=
|
||||
`($[$doc?:docComment]? @[$attrInstances,*] $vis:visibility meta def $declName:ident : Lean.ParserDescr :=
|
||||
ParserDescr.node $(quote stxNodeKind) $(quote prec) $val)
|
||||
trace `Elab fun _ => d
|
||||
withMacroExpansion stx d <| elabCommand d
|
||||
return stxNodeKind
|
||||
|
||||
@[builtin_command_elab «syntax»] private def elabSyntaxAux : CommandElab := fun stx =>
|
||||
discard <| elabSyntax stx
|
||||
|
||||
@[builtin_command_elab «syntaxAbbrev»] def elabSyntaxAbbrev : CommandElab := fun stx => do
|
||||
let `($[$doc?:docComment]? syntax $declName:ident := $[$ps:stx]*) ← pure stx | throwUnsupportedSyntax
|
||||
|
|
|
|||
|
|
@ -79,8 +79,13 @@ def addMacroStack {m} [Monad m] [MonadOptions m] (msgData : MessageData) (macroS
|
|||
msgData
|
||||
|
||||
def checkSyntaxNodeKind [Monad m] [MonadEnv m] [MonadError m] (k : Name) : m Name := do
|
||||
if Parser.isValidSyntaxNodeKind (← getEnv) k then pure k
|
||||
else throwError "failed"
|
||||
if Parser.isValidSyntaxNodeKind (← getEnv) k then
|
||||
return k
|
||||
if !(← getEnv).isExporting && !isPrivateName k then
|
||||
let k := mkPrivateName (← getEnv) k
|
||||
if Parser.isValidSyntaxNodeKind (← getEnv) k then
|
||||
return k
|
||||
throwError "failed"
|
||||
|
||||
def checkSyntaxNodeKindAtNamespaces [Monad m] [MonadEnv m] [MonadError m] (k : Name) : Name → m Name
|
||||
| n@(.str p _) => checkSyntaxNodeKind (n ++ k) <|> checkSyntaxNodeKindAtNamespaces k p
|
||||
|
|
|
|||
|
|
@ -885,6 +885,12 @@ used to generate visibility syntax for declarations that is independent of the p
|
|||
def visibility.ofBool (isPublic : Bool) : TSyntax ``visibility :=
|
||||
Unhygienic.run <| if isPublic then `(visibility| public) else `(visibility| private)
|
||||
|
||||
/--
|
||||
Returns syntax for `private` if `attrKind` is `local` and `public` otherwise.
|
||||
-/
|
||||
def visibility.ofAttrKind (attrKind : TSyntax ``Term.attrKind) : TSyntax ``visibility :=
|
||||
visibility.ofBool <| !attrKind matches `(attrKind| local)
|
||||
|
||||
end Command
|
||||
|
||||
namespace Term
|
||||
|
|
|
|||
5
tests/lean/run/localGlobalNotation.lean
Normal file
5
tests/lean/run/localGlobalNotation.lean
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
/-! `notation` should avoid name conflicts, also between local/global. -/
|
||||
namespace Foo
|
||||
|
||||
local notation "foo" => 1
|
||||
notation "foo" => 1
|
||||
|
|
@ -1,4 +1,6 @@
|
|||
scopedInstanceOutsideNamespace.lean:1:0-2:38: error: Scoped attributes must be used inside namespaces
|
||||
"true"
|
||||
scopedInstanceOutsideNamespace.lean:6:0-6:30: error: Scoped attributes must be used inside namespaces
|
||||
scopedInstanceOutsideNamespace.lean:6:0-6:30: error: invalid syntax node kind '«term_+__1»'
|
||||
scopedInstanceOutsideNamespace.lean:6:0-6:30: error: Scoped attributes must be used inside namespaces
|
||||
scopedInstanceOutsideNamespace.lean:8:2-8:17: error: Scoped attributes must be used inside namespaces
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
syntaxPrec.lean:1:17-1:21: error: unexpected token '<|>'; expected ':'
|
||||
[Elab.command] @[term_parser 1000]
|
||||
meta def «termFoo*_» : Lean.ParserDescr✝ :=
|
||||
public meta def «termFoo*_» : Lean.ParserDescr✝ :=
|
||||
ParserDescr.node✝ `«termFoo*_» 1022
|
||||
(ParserDescr.binary✝ `andthen (ParserDescr.symbol✝ "foo")
|
||||
(ParserDescr.binary✝ `orelse (ParserDescr.nodeWithAntiquot✝ "*" `token.«*» (ParserDescr.symbol✝ "*"))
|
||||
|
|
|
|||
|
|
@ -8,8 +8,11 @@ local infix:50 " ≺ " => LE.le
|
|||
|
||||
#check 1 ≺ 2
|
||||
|
||||
local macro "my_refl" : tactic =>
|
||||
`(tactic| rfl)
|
||||
-- It is possible to bind a local macro to a public auto param but we must opt into it explicitly by
|
||||
-- separating the `macro_rules` and removing the `local` from it.
|
||||
local syntax "my_refl" : tactic
|
||||
macro_rules
|
||||
| `(tactic| my_refl) => `(tactic| rfl)
|
||||
|
||||
def f (x y : Nat) (_h : x = y := by my_refl) := x
|
||||
|
||||
|
|
|
|||
1
tests/pkg/misc/lean-toolchain
Normal file
1
tests/pkg/misc/lean-toolchain
Normal file
|
|
@ -0,0 +1 @@
|
|||
lean4
|
||||
Loading…
Add table
Reference in a new issue